Browse Source

added libtomcrypt-1.05

Tom St Denis 20 years ago
parent
commit
9264e34ffb
49 changed files with 1008 additions and 109 deletions
  1. 1 1
      Doxyfile
  2. 9 9
      TODO
  3. 3 3
      build.sh
  4. 15 2
      changes
  5. 86 18
      crypt.tex
  6. 1 1
      demos/test.c
  7. BIN
      doc/crypt.pdf
  8. 19 16
      makefile
  9. 18 15
      makefile.icc
  10. 18 17
      makefile.msvc
  11. 19 16
      makefile.shared
  12. 91 0
      notes/tech0006.txt
  13. 2 2
      src/headers/tomcrypt.h
  14. 1 2
      src/headers/tomcrypt_cipher.h
  15. 22 0
      src/headers/tomcrypt_custom.h
  16. 2 0
      src/headers/tomcrypt_hash.h
  17. 30 0
      src/headers/tomcrypt_pk.h
  18. 1 0
      src/headers/tomcrypt_prng.h
  19. 3 0
      src/misc/crypt/crypt.c
  20. 2 0
      src/misc/crypt/crypt_cipher_descriptor.c
  21. 3 0
      src/misc/crypt/crypt_cipher_is_valid.c
  22. 3 0
      src/misc/crypt/crypt_find_cipher.c
  23. 3 0
      src/misc/crypt/crypt_find_cipher_any.c
  24. 5 1
      src/misc/crypt/crypt_find_cipher_id.c
  25. 3 0
      src/misc/crypt/crypt_find_hash.c
  26. 2 0
      src/misc/crypt/crypt_find_hash_any.c
  27. 7 3
      src/misc/crypt/crypt_find_hash_id.c
  28. 3 0
      src/misc/crypt/crypt_find_prng.c
  29. 3 0
      src/misc/crypt/crypt_hash_descriptor.c
  30. 3 0
      src/misc/crypt/crypt_hash_is_valid.c
  31. 3 0
      src/misc/crypt/crypt_prng_descriptor.c
  32. 3 0
      src/misc/crypt/crypt_prng_is_valid.c
  33. 4 0
      src/misc/crypt/crypt_register_cipher.c
  34. 4 0
      src/misc/crypt/crypt_register_hash.c
  35. 4 0
      src/misc/crypt/crypt_register_prng.c
  36. 3 0
      src/misc/crypt/crypt_unregister_cipher.c
  37. 3 0
      src/misc/crypt/crypt_unregister_hash.c
  38. 4 1
      src/misc/crypt/crypt_unregister_prng.c
  39. 168 0
      src/pk/asn1/der/choice/der_decode_choice.c
  40. 19 0
      src/pk/asn1/der/sequence/der_decode_sequence.c
  41. 4 0
      src/pk/asn1/der/sequence/der_decode_sequence_multi.c
  42. 16 0
      src/pk/asn1/der/sequence/der_encode_sequence.c
  43. 2 0
      src/pk/asn1/der/sequence/der_encode_sequence_multi.c
  44. 120 0
      src/pk/asn1/der/utctime/der_decode_utctime.c
  45. 80 0
      src/pk/asn1/der/utctime/der_encode_utctime.c
  46. 45 0
      src/pk/asn1/der/utctime/der_length_utctime.c
  47. 1 1
      src/pk/pkcs1/pkcs_1_oaep_decode.c
  48. 6 0
      src/pk/rsa/rsa_exptmod.c
  49. 141 1
      testprof/der_tests.c

+ 1 - 1
Doxyfile

@@ -23,7 +23,7 @@ PROJECT_NAME           = LibTomCrypt
 # This could be handy for archiving the generated documentation or 
 # if some version control system is used.
 
-PROJECT_NUMBER         = 1.04
+PROJECT_NUMBER         = 1.05
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
 # base path where the generated documentation will be put. 

+ 9 - 9
TODO

@@ -1,10 +1,10 @@
-Things ideal for 1.05
-
-- ASN.1 SET and UTCtime and CHOICE (hint for choice do it as a sep list and just use error codes to know when you got a hit)
-- Start working towards making the bignum code plugable
-- Add OID for ciphers and PRNGs to their descriptors
-- Document the ASN.1 a bit more verbosely ;-)
-- Some ASN.1 demo programs [for now read the source code!]
-- export ECC functions globally
-- Look into other ECC point muls and consider a "precomp" interface 
+For 1.06
 
+1. export ECC functions globally [e.g. mulmod and the sets]
+   - goal is tv_gen module and test vectors
+2. ASN.1 SET and T61String
+3. phase out DH code [RSA/ECC/DSA is enough]
+4. Some ASN.1 demo programs [for now read the source code!]
+5. Start working towards making the bignum code plugable
+6. Look into other ECC point muls and consider a "precomp" interface 
+7. Add OID for ciphers and PRNGs to their descriptors

+ 3 - 3
build.sh

@@ -2,7 +2,7 @@
 echo "$1 ($2, $3)..."
 make clean 1>/dev/null 2>/dev/null
 echo -n "building..."
-CFLAGS="$2 $CFLAGS" make -f $3 test tv_gen 1>gcc_1.txt 2>gcc_2.txt || (echo "build $1 failed see gcc_2.txt for more information" && cat gcc_2.txt && exit 1)
+CFLAGS="$2 $CFLAGS" make -j3 -f $3 test tv_gen 1>gcc_1.txt 2>gcc_2.txt || (echo "build $1 failed see gcc_2.txt for more information" && cat gcc_2.txt && exit 1)
 echo -n "testing..."
 if [ -a test ] && [ -f test ] && [ -x test ]; then
    ((./test >test_std.txt 2>test_err.txt && ./tv_gen > tv.txt) && echo "$1 test passed." && echo "y" > testok.txt) || (echo "$1 test failed" && cat test_err.txt && exit 1)
@@ -16,5 +16,5 @@ fi
 exit 1
 
 # $Source: /cvs/libtom/libtomcrypt/build.sh,v $   
-# $Revision: 1.4 $   
-# $Date: 2005/05/05 14:49:27 $ 
+# $Revision: 1.5 $   
+# $Date: 2005/06/27 13:04:05 $ 

+ 15 - 2
changes

@@ -1,3 +1,16 @@
+June 27th, 2005
+v1.05
+      -- Added Technote #6 which covers the current PK compliance.  
+      -- Fixed buffer overflow in OAEP decoder
+      -- Added CHOICE to the list of ASN.1 types
+      -- Added UTCTIME to the list of ASN.1 types
+      -- Added MUTEX locks around descriptor table functions [but not on the functions that are dependent on them]
+         All functions call *_is_valid() before using a descriptor index which means the respective table must be unlocked before 
+         it can be accessed.  However, during the operation [e.g. CCM] if the descriptor has been altered the results will be 
+         undefined.  
+      -- Minor updates to the manual to reflect recent changes
+      -- Added a catch to for an error that should never come up in rsa_exptmod().  Just being thorough.
+
 June 15th, 2005
 v1.04
       -- Fixed off by one [bit] error in dsa_make_key() it was too high by one bit [not a security problem just inconsistent]
@@ -1308,6 +1321,6 @@ v0.02  -- Changed RC5 to only allow 12 to 24 rounds
 v0.01  -- We will call this the first version.
 
 /* $Source: /cvs/libtom/libtomcrypt/changes,v $ */
-/* $Revision: 1.97 $ */
-/* $Date: 2005/06/14 23:09:41 $ */
+/* $Revision: 1.106 $ */
+/* $Date: 2005/06/27 12:37:06 $ */
 

+ 86 - 18
crypt.tex

@@ -47,7 +47,7 @@
 \def\gap{\vspace{0.5ex}}
 \makeindex
 \begin{document}
-\title{LibTomCrypt \\ Version 1.04}
+\title{LibTomCrypt \\ Version 1.05}
 \author{Tom St Denis \\
 \\
 [email protected] \\
@@ -3051,8 +3051,8 @@ int ecc_make_key(prng_state *prng, int wprng,
                  int keysize, ecc_key *key);
 \end{verbatim}
 
-The ``keysize'' is the size of the modulus in bytes desired.  Currently directly supported values are 20, 24, 28, 32, 48 and 65 bytes which
-correspond to key sizes of 160, 192, 224, 256, 384 and 521 bits respectively.  If you pass a key size that is between any key size
+The ``keysize'' is the size of the modulus in bytes desired.  Currently directly supported values are 24, 28, 32, 48 and 65 bytes which
+correspond to key sizes of 192, 224, 256, 384 and 521 bits respectively.  If you pass a key size that is between any key size
 it will round the keysize up to the next available one.  The rest of the parameters work like they do in the ``dh\_make\_key()'' function.  
 To free the ram allocated by a key call:
 \index{ecc\_free()}
@@ -3150,8 +3150,8 @@ The signature code is an implementation of X9.62 EC-DSA and the output is comfor
 \section{ECC Keysizes}
 With ECC if you try and sign a hash that is bigger than your ECC key you can run into problems.  The math will still work
 and in effect the signature will still work.  With ECC keys the strength of the signature is limited by the size of
-the hash or the size of they key, whichever is smaller.  For example, if you sign with SHA256 and a ECC-160 key in effect
-you have 160-bits of security (e.g. as if you signed with SHA-1).  
+the hash or the size of they key, whichever is smaller.  For example, if you sign with SHA256 and an ECC-192 key in effect
+you have 192-bits of security.  
 
 The library will not warn you if you make this mistake so it is important to check yourself before using the 
 signatures.
@@ -3324,7 +3324,7 @@ LibTomCrypt supports a variety of ASN.1 data types encoded with the Distinguishe
 are all provided with three basic functions with \textit{similar} prototypes.  One function has been dedicated to calculate the length in octets of a given
 format and two functions have been dedicated to encoding and decoding the format.  
 
-On top of the basic data types are the SEQUENCE and\footnote{Planned for LTC 1.04} SET data types which are collections of other ASN.1 types.  They are provided 
+On top of the basic data types are the SEQUENCE and\footnote{Planned for LTC 1.06} SET data types which are collections of other ASN.1 types.  They are provided 
 in the same manner as the other data types except they use list of objects known as the \textbf{ltc\_asn1\_list} structure.  It is defined as 
 
 \index{ltc\_asn1\_list structure}
@@ -3333,11 +3333,13 @@ typedef struct {
    int           type;
    void         *data;
    unsigned long size;
+   int           used;
 } ltc_asn1_list;
 \end{verbatim}
 
 The ``type'' field is one of the following ASN.1 field definitions.  The ``data'' pointer is a void pointer to the data to be encoded (or the destination) and the 
-``size'' field is specific to what you are encoding (e.g. number of bits in the BIT STRING data type).  To help build the lists in an orderly fashion the macro
+``size'' field is specific to what you are encoding (e.g. number of bits in the BIT STRING data type).  The ``used'' field is primarily for the CHOICE decoder
+and reflects if the particular member of a list was the decoded data type.  To help build the lists in an orderly fashion the macro
 ``LTC\_SET\_ASN1(list, index, Type, Data, Size)'' has been provided.
 
 It will assign to the ``index''th position in the ``list'' the tripplet (Type, Data, Size).  An example usage would be:
@@ -3382,7 +3384,9 @@ LTC_SET_ASN1(sequence, x++, LTC_ASN1_NULL,           NULL,   0);
 \hline LTC\_ASN1\_OBJECT\_IDENTIFIER & OBJECT IDENTIFIER (words are in unsigned long) \\
 \hline LTC\_ASN1\_IA5\_STRING        & IA5 STRING (one octet per char) \\
 \hline LTC\_ASN1\_PRINTABLE\_STRING  & PRINTABLE STIRNG (one octet per char) \\
+\hline LTC\_ASN1\_UTCTIME            & UTCTIME (see ltc\_utctime structure) \\
 \hline LTC\_ASN1\_SEQUENCE           & SEQUENCE OF \\
+\hline LTC\_ASN1\_CHOICE             & CHOICE \\
 \hline
 \end{tabular}
 \caption{List of ASN.1 Supported Types}
@@ -3466,7 +3470,7 @@ and ``data'' is \textbf{void} pointer.  The list of items must be terminated wit
 It's ideal that you cast the ``size'' values to unsigned long to ensure that the proper data type is passed to the function.  Constants such as ``1'' without
 a cast or prototype are of type \textbf{int} by default.  Appending \textit{UL} or prepending \textit{(unsigned long)} is enough to cast it to the correct type.
 
-\subsubsection{ASN.1 INTEGER}
+\subsection{ASN.1 INTEGER}
 
 To encode or decode INTEGER data types use the following functions.
 
@@ -3498,7 +3502,7 @@ int der_length_short_integer(unsigned long num, unsigned long *outlen);
 These will encode or decode an unsigned \textbf{unsigned long} type (only reads upto 32--bits).  For values in the range $0 \dots 2^{32} - 1$ the integer 
 and short integer functions can encode and decode each others outputs.  
 
-\subsubsection{ASN.1 BIT STRING}
+\subsection{ASN.1 BIT STRING}
 
 \index{der\_encode\_bit\_string()}
 \index{der\_decode\_bit\_string()}
@@ -3516,7 +3520,7 @@ int der_length_bit_string(unsigned long nbits, unsigned long *outlen);
 These will encode or decode a BIT STRING data type.  The bits are passed in (or read out) using one \textbf{char} per bit.  A non--zero value will be interpretted
 as a one bit and a zero value a zero bit.
 
-\subsubsection{ASN.1 OCTET STRING}
+\subsection{ASN.1 OCTET STRING}
 
 \index{der\_encode\_octet\_string()}
 \index{der\_decode\_octet\_string()}
@@ -3533,7 +3537,7 @@ int der_length_octet_string(unsigned long noctets, unsigned long *outlen);
 
 These will encode or decode an OCTET STRING data type.  The octets are stored using one \textbf{char} each.  
 
-\subsubsection{ASN.1 OBJECT IDENTIFIER}
+\subsection{ASN.1 OBJECT IDENTIFIER}
 
 \index{der\_encode\_object\_identifier()}
 \index{der\_decode\_object\_identifier()}
@@ -3552,7 +3556,7 @@ int der_length_object_identifier(unsigned long *words, unsigned long nwords,
 These will encode or decode an OBJECT IDENTIFIER object.  The words of the OID are stored in individual \textbf{unsigned long} elements and must be in the range
 $0 \ldots 2^{32} - 1$.  
 
-\subsubsection{ASN.1 IA5 STRING}
+\subsection{ASN.1 IA5 STRING}
 
 \index{der\_encode\_ia5\_string()}
 \index{der\_decode\_ia5\_string()}
@@ -3575,7 +3579,7 @@ that the build platform honours the runtime platforms character conventions.
 
 If you're worried try building the test suite and running it.  It has hard coded test vectors to ensure it is operating properly. 
 
-\subsubsection{ASN.1 PRINTABLE STRING}
+\subsection{ASN.1 PRINTABLE STRING}
 
 \index{der\_encode\_printable\_string()}
 \index{der\_decode\_printable\_string()}
@@ -3598,6 +3602,64 @@ that the build platform honours the runtime platforms character conventions.
 
 If you're worried try building the test suite and running it.  It has hard coded test vectors to ensure it is operating properly. 
 
+\subsection{ASN.1 UTCTIME}
+
+The UTCTIME type is to store a date and time in ASN.1 format.  It uses the following structure to organize the time.
+
+\begin{verbatim}
+typedef struct {
+   unsigned YY, /* year    00--99 */
+            MM, /* month   01--12 */
+            DD, /* day     01--31 */
+            hh, /* hour    00--23 */
+            mm, /* minute  00--59 */
+            ss, /* second  00--59 */
+            off_dir, /* timezone offset direction 0 == +, 1 == - */
+            off_hh, /* timezone offset hours */
+            off_mm; /* timezone offset minutes */
+} ltc_utctime;
+\end{verbatim}
+
+The time can be offset plus or minus a set amount of hours (off\_hh) and minutes (off\_mm).  When ``off\_dir'' is zero the time will be added otherwise it 
+will be subtracted.  
+
+For instance, the array $\lbrace 5, 6, 20, 22, 4, 00, 0, 5, 0 \rbrace$ represents the current time of 2005, June 20th, 22:04:00 with a time offset of +05h00.  
+
+\index{der\_encode\_utctime()}
+\index{der\_decode\_utctime()}
+\index{der\_length\_utctime()}
+\begin{verbatim}
+int der_encode_utctime(ltc_utctime *utctime, 
+                       unsigned char *out,   unsigned long *outlen);
+
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+                             ltc_utctime   *out);
+
+int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen);
+\end{verbatim}
+
+The encoder will store time in one of the two ASN.1 formats, either ``YYMMDDhhmmssZ'' or ``YYMMDDhhmmss$\pm$hhmm'' and perform minimal error checking on the 
+input.  The decoder will read all valid ASN.1 formats and perform range checking on the values (not complete but rational) useful for catching packet errors.
+
+It is suggested that decoded data be further scrutinized (e.g. days of month in particular).
+
+\subsection{ASN.1 CHOICE}
+
+The CHOICE ASN.1 type represents a union of ASN.1 types all of which are stored in a ``ltc\_asn1\_list''.  There is no encoder for the CHOICE type, only a 
+decoder.  The decoder will scan through the provided list attempting to use the appropriate decoder on the input packet.  The list can contain any ASN.1 data
+type\footnote{Except it cannot have LTC\_ASN1\_INTEGER and LTC\_ASN1\_SHORT\_INTEGER simultaneously.} except for other CHOICE types.  
+
+There is no encoder for the CHOICE type as the actual DER encoding is the encoding of the chosen type.  
+
+\index{der\_decode\_choice()}
+\begin{verbatim}
+int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
+                            ltc_asn1_list *list, unsigned long  outlen);
+\end{verbatim}
+
+This will decode the input in the ``in'' field of length ``inlen''.  It uses the provided ASN.1 list specified in the ``list'' field which has ``outlen'' elements.  
+The ``inlen'' field will be updated with the length of the decoded data type as well as the respective entry in the ``list'' field will have the ``used'' flag 
+set to non--zero to reflect it was the data type decoded.
 
 \section{Password Based Cryptography}
 \subsection{PKCS \#5}
@@ -3871,7 +3933,6 @@ $n$ it requires $\sqrt n$ work.  The following table sumarizes the work required
 \begin{center}
 \begin{tabular}{|c|c|}
     \hline ECC Key Size (bits) & Work Factor ($log_2$) \\
-    \hline 160 & 80  \\
     \hline 192 & 96  \\
     \hline 224 & 112 \\
     \hline 256 & 128 \\
@@ -4029,8 +4090,8 @@ will increase by approximately 500 bytes.  If this is defined but TWOFISH\_SMALL
 it will not speed up the encryption or decryption functions.
 
 \subsection{GCM\_TABLES}
-When defined GCM will use a 64KB table (per GCM state) which will greatly lower up the per--packet latency.  
-It also increases the initialization time.  
+When defined GCM will use a 64KB table (per GCM state) which will greatly speed up the per--packet latency.  
+It also increases the initialization time and isn't suitable when you are going to use a key a few times only.  
 
 \subsection{SMALL\_CODE}
 When this is defined some of the code such as the Rijndael and SAFER+ ciphers are replaced with smaller code variants.
@@ -4061,6 +4122,13 @@ data type you can perform integer operations with.  Ideally it should be four or
 of your block cipher (e.g. 16 bytes for AES).  This means sadly if you're on a platform with 57--bit words (or something) you can't 
 use this mode.  So sad.
 
+\subsection{LTC\_PTHREAD}
+When this is activated all of the descriptor table functions will use pthread locking to ensure thread safe updates to the tables.  Note that 
+it doesn't prevent a thread that is passively using a table from being messed up by another thread that updates the table.
+
+Generally the rule of thumb is to setup the tables once at startup and then leave them be.  This added build flag simply makes updating
+the tables safer.
+
 \section{MPI Tweaks}
 \subsection{RSA Only Tweak}
 If you plan on only using RSA with moduli in the range of 1024 to 2560 bits you can enable a series of tweaks
@@ -4491,5 +4559,5 @@ but should at least maintain the same level of state entropy.
 \end{document}
 
 % $Source: /cvs/libtom/libtomcrypt/crypt.tex,v $   
-% $Revision: 1.33 $   
-% $Date: 2005/06/14 22:53:24 $ 
+% $Revision: 1.39 $   
+% $Date: 2005/06/27 13:08:28 $ 

+ 1 - 1
demos/test.c

@@ -8,8 +8,8 @@ int main(void)
    printf("\nstore_test...."); fflush(stdout); x = store_test();       printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);
    printf("\ncipher_test..."); fflush(stdout); x = cipher_hash_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);
    printf("\nmodes_test...."); fflush(stdout); x = modes_test();       printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);
-   printf("\nmac_test......"); fflush(stdout); x = mac_test();         printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);
    printf("\nder_test......"); fflush(stdout); x = der_tests();        printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);
+   printf("\nmac_test......"); fflush(stdout); x = mac_test();         printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);
    printf("\npkcs_1_test..."); fflush(stdout); x = pkcs_1_test();      printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);
    printf("\nrsa_test......"); fflush(stdout); x = rsa_test();         printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);
    printf("\necc_test......"); fflush(stdout); x = ecc_tests();        printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE);

BIN
doc/crypt.pdf


+ 19 - 16
makefile

@@ -4,7 +4,7 @@
 # Modified by Clay Culver
 
 # The version
-VERSION=1.04
+VERSION=1.05
 
 # Compiler and Linker Names
 #CC=gcc
@@ -132,9 +132,10 @@ src/modes/ecb/ecb_start.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \
 src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \
 src/modes/ofb/ofb_start.o src/pk/asn1/der/bit/der_decode_bit_string.o \
 src/pk/asn1/der/bit/der_encode_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \
-src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \
-src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \
-src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \
+src/pk/asn1/der/choice/der_decode_choice.o src/pk/asn1/der/ia5/der_decode_ia5_string.o \
+src/pk/asn1/der/ia5/der_encode_ia5_string.o src/pk/asn1/der/ia5/der_length_ia5_string.o \
+src/pk/asn1/der/integer/der_decode_integer.o src/pk/asn1/der/integer/der_encode_integer.o \
+src/pk/asn1/der/integer/der_length_integer.o \
 src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \
 src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \
 src/pk/asn1/der/object_identifier/der_length_object_identifier.o \
@@ -148,16 +149,18 @@ src/pk/asn1/der/sequence/der_encode_sequence.o src/pk/asn1/der/sequence/der_enco
 src/pk/asn1/der/sequence/der_length_sequence.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/dh/dh.o src/pk/dsa/dsa_export.o \
-src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \
-src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o \
-src/pk/packet_valid_header.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \
-src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \
-src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o \
-src/pk/rsa/rsa_encrypt_key.o src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o \
-src/pk/rsa/rsa_import.o src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o \
-src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o src/prngs/rc4.o src/prngs/rng_get_bytes.o \
-src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o src/prngs/yarrow.o 
+src/pk/asn1/der/short_integer/der_length_short_integer.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/dh/dh.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o \
+src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \
+src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o src/pk/packet_valid_header.o \
+src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o src/pk/pkcs1/pkcs_1_oaep_decode.o \
+src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o src/pk/pkcs1/pkcs_1_pss_decode.o \
+src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \
+src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_import.o \
+src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o \
+src/prngs/rc4.o src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o \
+src/prngs/sprng.o src/prngs/yarrow.o 
 
 HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h \
 src/headers/tomcrypt_macros.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \
@@ -321,5 +324,5 @@ zipup: no_oops docs
 
 
 # $Source: /cvs/libtom/libtomcrypt/makefile,v $ 
-# $Revision: 1.68 $ 
-# $Date: 2005/06/14 22:53:24 $ 
+# $Revision: 1.70 $ 
+# $Date: 2005/06/19 18:03:24 $ 

+ 18 - 15
makefile.icc

@@ -130,9 +130,10 @@ src/modes/ecb/ecb_start.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \
 src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \
 src/modes/ofb/ofb_start.o src/pk/asn1/der/bit/der_decode_bit_string.o \
 src/pk/asn1/der/bit/der_encode_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \
-src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \
-src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \
-src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \
+src/pk/asn1/der/choice/der_decode_choice.o src/pk/asn1/der/ia5/der_decode_ia5_string.o \
+src/pk/asn1/der/ia5/der_encode_ia5_string.o src/pk/asn1/der/ia5/der_length_ia5_string.o \
+src/pk/asn1/der/integer/der_decode_integer.o src/pk/asn1/der/integer/der_encode_integer.o \
+src/pk/asn1/der/integer/der_length_integer.o \
 src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \
 src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \
 src/pk/asn1/der/object_identifier/der_length_object_identifier.o \
@@ -146,16 +147,18 @@ src/pk/asn1/der/sequence/der_encode_sequence.o src/pk/asn1/der/sequence/der_enco
 src/pk/asn1/der/sequence/der_length_sequence.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/dh/dh.o src/pk/dsa/dsa_export.o \
-src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \
-src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o \
-src/pk/packet_valid_header.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \
-src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \
-src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o \
-src/pk/rsa/rsa_encrypt_key.o src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o \
-src/pk/rsa/rsa_import.o src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o \
-src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o src/prngs/rc4.o src/prngs/rng_get_bytes.o \
-src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o src/prngs/yarrow.o 
+src/pk/asn1/der/short_integer/der_length_short_integer.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/dh/dh.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o \
+src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \
+src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o src/pk/packet_valid_header.o \
+src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o src/pk/pkcs1/pkcs_1_oaep_decode.o \
+src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o src/pk/pkcs1/pkcs_1_pss_decode.o \
+src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \
+src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_import.o \
+src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o \
+src/prngs/rc4.o src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o \
+src/prngs/sprng.o src/prngs/yarrow.o 
 
 HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h \
 src/headers/tomcrypt_macros.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \
@@ -235,5 +238,5 @@ install: library
 	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
 
 # $Source: /cvs/libtom/libtomcrypt/makefile.icc,v $   
-# $Revision: 1.32 $   
-# $Date: 2005/05/23 03:12:44 $ 
+# $Revision: 1.33 $   
+# $Date: 2005/06/19 18:22:31 $ 

+ 18 - 17
makefile.msvc

@@ -59,9 +59,10 @@ src/modes/ecb/ecb_start.obj src/modes/ofb/ofb_decrypt.obj src/modes/ofb/ofb_done
 src/modes/ofb/ofb_encrypt.obj src/modes/ofb/ofb_getiv.obj src/modes/ofb/ofb_setiv.obj \
 src/modes/ofb/ofb_start.obj src/pk/asn1/der/bit/der_decode_bit_string.obj \
 src/pk/asn1/der/bit/der_encode_bit_string.obj src/pk/asn1/der/bit/der_length_bit_string.obj \
-src/pk/asn1/der/ia5/der_decode_ia5_string.obj src/pk/asn1/der/ia5/der_encode_ia5_string.obj \
-src/pk/asn1/der/ia5/der_length_ia5_string.obj src/pk/asn1/der/integer/der_decode_integer.obj \
-src/pk/asn1/der/integer/der_encode_integer.obj src/pk/asn1/der/integer/der_length_integer.obj \
+src/pk/asn1/der/choice/der_decode_choice.obj src/pk/asn1/der/ia5/der_decode_ia5_string.obj \
+src/pk/asn1/der/ia5/der_encode_ia5_string.obj src/pk/asn1/der/ia5/der_length_ia5_string.obj \
+src/pk/asn1/der/integer/der_decode_integer.obj src/pk/asn1/der/integer/der_encode_integer.obj \
+src/pk/asn1/der/integer/der_length_integer.obj \
 src/pk/asn1/der/object_identifier/der_decode_object_identifier.obj \
 src/pk/asn1/der/object_identifier/der_encode_object_identifier.obj \
 src/pk/asn1/der/object_identifier/der_length_object_identifier.obj \
@@ -75,16 +76,18 @@ src/pk/asn1/der/sequence/der_encode_sequence.obj src/pk/asn1/der/sequence/der_en
 src/pk/asn1/der/sequence/der_length_sequence.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/dh/dh.obj src/pk/dsa/dsa_export.obj \
-src/pk/dsa/dsa_free.obj src/pk/dsa/dsa_import.obj src/pk/dsa/dsa_make_key.obj src/pk/dsa/dsa_sign_hash.obj \
-src/pk/dsa/dsa_verify_hash.obj src/pk/dsa/dsa_verify_key.obj src/pk/ecc/ecc.obj src/pk/packet_store_header.obj \
-src/pk/packet_valid_header.obj src/pk/pkcs1/pkcs_1_i2osp.obj src/pk/pkcs1/pkcs_1_mgf1.obj \
-src/pk/pkcs1/pkcs_1_oaep_decode.obj src/pk/pkcs1/pkcs_1_oaep_encode.obj src/pk/pkcs1/pkcs_1_os2ip.obj \
-src/pk/pkcs1/pkcs_1_pss_decode.obj src/pk/pkcs1/pkcs_1_pss_encode.obj src/pk/rsa/rsa_decrypt_key.obj \
-src/pk/rsa/rsa_encrypt_key.obj src/pk/rsa/rsa_export.obj src/pk/rsa/rsa_exptmod.obj src/pk/rsa/rsa_free.obj \
-src/pk/rsa/rsa_import.obj src/pk/rsa/rsa_make_key.obj src/pk/rsa/rsa_sign_hash.obj \
-src/pk/rsa/rsa_verify_hash.obj src/prngs/fortuna.obj src/prngs/rc4.obj src/prngs/rng_get_bytes.obj \
-src/prngs/rng_make_prng.obj src/prngs/sober128.obj src/prngs/sprng.obj src/prngs/yarrow.obj 
+src/pk/asn1/der/short_integer/der_length_short_integer.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/dh/dh.obj src/pk/dsa/dsa_export.obj src/pk/dsa/dsa_free.obj src/pk/dsa/dsa_import.obj \
+src/pk/dsa/dsa_make_key.obj src/pk/dsa/dsa_sign_hash.obj src/pk/dsa/dsa_verify_hash.obj \
+src/pk/dsa/dsa_verify_key.obj src/pk/ecc/ecc.obj src/pk/packet_store_header.obj src/pk/packet_valid_header.obj \
+src/pk/pkcs1/pkcs_1_i2osp.obj src/pk/pkcs1/pkcs_1_mgf1.obj src/pk/pkcs1/pkcs_1_oaep_decode.obj \
+src/pk/pkcs1/pkcs_1_oaep_encode.obj src/pk/pkcs1/pkcs_1_os2ip.obj src/pk/pkcs1/pkcs_1_pss_decode.obj \
+src/pk/pkcs1/pkcs_1_pss_encode.obj src/pk/rsa/rsa_decrypt_key.obj src/pk/rsa/rsa_encrypt_key.obj \
+src/pk/rsa/rsa_export.obj src/pk/rsa/rsa_exptmod.obj src/pk/rsa/rsa_free.obj src/pk/rsa/rsa_import.obj \
+src/pk/rsa/rsa_make_key.obj src/pk/rsa/rsa_sign_hash.obj src/pk/rsa/rsa_verify_hash.obj src/prngs/fortuna.obj \
+src/prngs/rc4.obj src/prngs/rng_get_bytes.obj src/prngs/rng_make_prng.obj src/prngs/sober128.obj \
+src/prngs/sprng.obj src/prngs/yarrow.obj 
 
 HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h \
 src/headers/tomcrypt_macros.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \
@@ -92,8 +95,6 @@ src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h src/headers/tommath_clas
 src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h src/headers/tomcrypt_misc.h \
 src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h
 
-
-
 #ciphers come in two flavours... enc+dec and enc
 src/ciphers/aes/aes_enc.obj: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c
 	$(CC) $(CFLAGS) /DENCRYPT_ONLY /c src/ciphers/aes/aes.c /Fosrc/ciphers/aes/aes_enc.obj
@@ -117,5 +118,5 @@ timing: demos/timing.c library
 	cl $(CFLAGS) demos/timing.c testprof/tomcrypt_prof.lib tomcrypt.lib advapi32.lib
 
 # $Source: /cvs/libtom/libtomcrypt/makefile.msvc,v $   
-# $Revision: 1.14 $   
-# $Date: 2005/06/08 23:37:40 $ 
+# $Revision: 1.15 $   
+# $Date: 2005/06/27 12:37:06 $ 

+ 19 - 16
makefile.shared

@@ -6,7 +6,7 @@
 # Tom St Denis
 
 # The version
-VERSION=0:104
+VERSION=0:105
 
 # Compiler and Linker Names
 CC=libtool --mode=compile gcc
@@ -131,9 +131,10 @@ src/modes/ecb/ecb_start.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \
 src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \
 src/modes/ofb/ofb_start.o src/pk/asn1/der/bit/der_decode_bit_string.o \
 src/pk/asn1/der/bit/der_encode_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \
-src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \
-src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \
-src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \
+src/pk/asn1/der/choice/der_decode_choice.o src/pk/asn1/der/ia5/der_decode_ia5_string.o \
+src/pk/asn1/der/ia5/der_encode_ia5_string.o src/pk/asn1/der/ia5/der_length_ia5_string.o \
+src/pk/asn1/der/integer/der_decode_integer.o src/pk/asn1/der/integer/der_encode_integer.o \
+src/pk/asn1/der/integer/der_length_integer.o \
 src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \
 src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \
 src/pk/asn1/der/object_identifier/der_length_object_identifier.o \
@@ -147,16 +148,18 @@ src/pk/asn1/der/sequence/der_encode_sequence.o src/pk/asn1/der/sequence/der_enco
 src/pk/asn1/der/sequence/der_length_sequence.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/dh/dh.o src/pk/dsa/dsa_export.o \
-src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \
-src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o \
-src/pk/packet_valid_header.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \
-src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \
-src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o \
-src/pk/rsa/rsa_encrypt_key.o src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o \
-src/pk/rsa/rsa_import.o src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o \
-src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o src/prngs/rc4.o src/prngs/rng_get_bytes.o \
-src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o src/prngs/yarrow.o 
+src/pk/asn1/der/short_integer/der_length_short_integer.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/dh/dh.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o \
+src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \
+src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o src/pk/packet_valid_header.o \
+src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o src/pk/pkcs1/pkcs_1_oaep_decode.o \
+src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o src/pk/pkcs1/pkcs_1_pss_decode.o \
+src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \
+src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_import.o \
+src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o \
+src/prngs/rc4.o src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o \
+src/prngs/sprng.o src/prngs/yarrow.o 
 
 HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h \
 src/headers/tomcrypt_macros.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \
@@ -222,5 +225,5 @@ timing: library $(LIBTEST) $(TIMINGS)
 	gcc -o $(TIMING) $(TIMINGS) -ltomcrypt_prof -ltomcrypt $(MPISHARED)
 
 # $Source: /cvs/libtom/libtomcrypt/makefile.shared,v $   
-# $Revision: 1.17 $   
-# $Date: 2005/06/14 22:53:25 $ 
+# $Revision: 1.19 $   
+# $Date: 2005/06/27 12:37:06 $ 

+ 91 - 0
notes/tech0006.txt

@@ -0,0 +1,91 @@
+Tech Note 0006
+PK Standards Compliance
+Tom St Denis
+
+RSA
+----
+
+PKCS #1 compliance.
+
+Key Format:  RSAPublicKey and RSAPrivateKey as per PKCS #1 v2.1
+Encryption:  OAEP as per PKCS #1
+Signature :  PSS  as per PKCS #1
+
+DSA
+----
+
+The NIST DSA algorithm
+
+Key Format:  HomeBrew [see below]
+Signature :  ANSI X9.62 format [see below].
+
+Keys are stored as 
+
+DSAPublicKey ::= SEQUENCE {
+    publicFlags    BIT STRING(1), -- must be 0
+    g              INTEGER      , -- base generator, check that g^q mod p == 1
+                                  -- and that 1 < g < p - 1
+    p              INTEGER      , -- prime modulus 
+    q              INTEGER      , -- order of sub-group (must be prime)
+    y              INTEGER      , -- public key, specifically, g^x mod p, 
+                                  -- check that y^q mod p == 1
+                                  -- and that 1 < y < p - 1
+}
+
+DSAPrivateKey ::= SEQUENCE {
+    publicFlags    BIT STRING(1), -- must be 1
+    g              INTEGER      , -- base generator, check that g^q mod p == 1
+                                  -- and that 1 < g < p - 1
+    p              INTEGER      , -- prime modulus 
+    q              INTEGER      , -- order of sub-group (must be prime)
+    y              INTEGER      , -- public key, specifically, g^x mod p, 
+                                  -- check that y^q mod p == 1
+                                  -- and that 1 < y < p - 1
+    x              INTEGER        -- private key
+}
+
+Signatures are stored as 
+
+DSASignature ::= SEQUENCE {
+    r, s           INTEGER        -- signature parameters
+}
+
+ECC
+----
+
+The ANSI X9.62 and X9.63 algorithms [partial].  Supports all NIST GF(p) curves.
+
+Key Format   :  Homebrew [see below, only GF(p) NIST curves supported]
+Signature    :  X9.62 compliant
+Encryption   :  Homebrew [based on X9.63, differs in that the public point is stored as an ECCPublicKey]
+Shared Secret:  X9.63 compliant
+
+ECCPublicKey ::= SEQUENCE {
+    flags       BIT STRING(1), -- public/private flag (always zero), 
+    keySize     INTEGER,       -- Curve size (in bits) divided by eight 
+                               -- and rounded down, e.g. 521 => 65
+    pubkey.x    INTEGER,       -- The X co-ordinate of the public key point
+    pubkey.y    INTEGER,       -- The Y co-ordinate of the public key point
+}
+
+ECCPrivateKey ::= SEQUENCE {
+    flags       BIT STRING(1), -- public/private flag (always one), 
+    keySize     INTEGER,       -- Curve size (in bits) divided by eight 
+                               -- and rounded down, e.g. 521 => 65
+    pubkey.x    INTEGER,       -- The X co-ordinate of the public key point
+    pubkey.y    INTEGER,       -- The Y co-ordinate of the public key point
+    secret.k    INTEGER,       -- The secret key scalar
+}
+
+The encryption works by finding the X9.63 shared secret and hashing it.  The hash is then simply XOR'ed against the message [which must be at most the size
+of the hash digest].  The format of the encrypted text is as follows
+
+ECCEncrypted ::= SEQUENCE {
+    hashOID     OBJECT IDENTIFIER,   -- The OID of the hash used
+    pubkey      OCTET STRING     ,   -- Encapsulation of a random ECCPublicKey
+    skey        OCTET STRING         -- The encrypted text (which the hash was XOR'ed against)
+}
+
+% $Source: /cvs/libtom/libtomcrypt/notes/tech0006.txt,v $   
+% $Revision: 1.2 $   
+% $Date: 2005/06/18 02:26:27 $ 

+ 2 - 2
src/headers/tomcrypt.h

@@ -16,8 +16,8 @@ extern "C" {
 #endif
 
 /* version */
-#define CRYPT   0x0104
-#define SCRYPT  "1.04"
+#define CRYPT   0x0105
+#define SCRYPT  "1.05"
 
 /* max size of either a cipher/hash block or symmetric key [largest of the two] */
 #define MAXBLOCKSIZE  128

+ 1 - 2
src/headers/tomcrypt_cipher.h

@@ -618,12 +618,11 @@ int ctr_done(symmetric_CTR *ctr);
 int find_cipher(const char *name);
 int find_cipher_any(const char *name, int blocklen, int keylen);
 int find_cipher_id(unsigned char ID);
-
 int register_cipher(const struct ltc_cipher_descriptor *cipher);
 int unregister_cipher(const struct ltc_cipher_descriptor *cipher);
-
 int cipher_is_valid(int idx);
 
+LTC_MUTEX_PROTO(ltc_cipher_mutex);
 
 /* $Source$ */
 /* $Revision$ */

+ 22 - 0
src/headers/tomcrypt_custom.h

@@ -229,6 +229,28 @@
 #endif
 
 
+/* THREAD management */
+
+#ifdef LTC_PTHREAD
+
+#include <pthread.h>
+
+#define LTC_MUTEX_GLOBAL(x)   pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
+#define LTC_MUTEX_PROTO(x)    extern pthread_mutex_t x;
+#define LTC_MUTEX_LOCK(x)     pthread_mutex_lock(x);
+#define LTC_MUTEX_UNLOCK(x)   pthread_mutex_unlock(x);
+
+#else 
+
+/* default no functions */
+#define LTC_MUTEX_GLOBAL(x)
+#define LTC_MUTEX_PROTO(x)
+#define LTC_MUTEX_LOCK(x)
+#define LTC_MUTEX_UNLOCK(x)
+
+#endif
+
+
 /* $Source$ */
 /* $Revision$ */
 /* $Date$ */

+ 2 - 0
src/headers/tomcrypt_hash.h

@@ -279,6 +279,8 @@ int register_hash(const struct ltc_hash_descriptor *hash);
 int unregister_hash(const struct ltc_hash_descriptor *hash);
 int hash_is_valid(int idx);
 
+LTC_MUTEX_PROTO(ltc_hash_mutex);
+
 int hash_memory(int hash, 
                 const unsigned char *in,  unsigned long inlen, 
                       unsigned char *out, unsigned long *outlen);

+ 30 - 0
src/headers/tomcrypt_pk.h

@@ -259,7 +259,9 @@ enum {
  LTC_ASN1_OBJECT_IDENTIFIER,
  LTC_ASN1_IA5_STRING,
  LTC_ASN1_PRINTABLE_STRING,
+ LTC_ASN1_UTCTIME,
 
+ LTC_ASN1_CHOICE,
  LTC_ASN1_SEQUENCE
 };
 
@@ -267,6 +269,7 @@ typedef struct {
    int           type;
    void         *data;
    unsigned long size;
+   int           used;
 } ltc_asn1_list;
 
 #define LTC_SET_ASN1(list, index, Type, Data, Size)  \
@@ -276,6 +279,7 @@ typedef struct {
       LTC_MACRO_list[LTC_MACRO_temp].type = (Type);  \
       LTC_MACRO_list[LTC_MACRO_temp].data = (Data);  \
       LTC_MACRO_list[LTC_MACRO_temp].size = (Size);  \
+      LTC_MACRO_list[LTC_MACRO_temp].used = 0;       \
    } while (0);
 
 /* SEQUENCE */
@@ -344,6 +348,32 @@ int der_length_printable_string(const unsigned char *octets, unsigned long nocte
 int der_printable_char_encode(int c);
 int der_printable_value_decode(int v);
 
+/* CHOICE */
+int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
+                            ltc_asn1_list *list, unsigned long  outlen);
+
+/* UTCTime */
+typedef struct {
+   unsigned YY, /* year */
+            MM, /* month */
+            DD, /* day */
+            hh, /* hour */
+            mm, /* minute */
+            ss, /* second */
+            off_dir, /* timezone offset direction 0 == +, 1 == - */
+            off_hh, /* timezone offset hours */
+            off_mm; /* timezone offset minutes */
+} ltc_utctime;
+
+int der_encode_utctime(ltc_utctime *utctime, 
+                       unsigned char *out,   unsigned long *outlen);
+
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+                             ltc_utctime   *out);
+
+int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen);
+
+
 #endif
 
 /* $Source$ */

+ 1 - 0
src/headers/tomcrypt_prng.h

@@ -178,6 +178,7 @@ int find_prng(const char *name);
 int register_prng(const struct ltc_prng_descriptor *prng);
 int unregister_prng(const struct ltc_prng_descriptor *prng);
 int prng_is_valid(int idx);
+LTC_MUTEX_PROTO(ltc_prng_mutex);
 
 /* Slow RNG you **might** be able to use to seed a PRNG with.  Be careful as this
  * might not work on all platforms as planned

+ 3 - 0
src/misc/crypt/crypt.c

@@ -301,6 +301,9 @@ const char *crypt_build_settings =
 #endif
 #if defined(LTC_NO_TABLES)
     " LTC_NO_TABLES "
+#endif
+#if defined(LTC_PTHREAD)
+    " LTC_PTHREAD "
 #endif
     "\n"
     "\n\n\n"

+ 2 - 0
src/misc/crypt/crypt_cipher_descriptor.c

@@ -19,6 +19,8 @@ struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = {
 { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
  };
 
+LTC_MUTEX_GLOBAL(ltc_cipher_mutex);
+
 
 /* $Source$ */
 /* $Revision$ */

+ 3 - 0
src/misc/crypt/crypt_cipher_is_valid.c

@@ -22,9 +22,12 @@
 */
 int cipher_is_valid(int idx)
 {
+   LTC_MUTEX_LOCK(&ltc_cipher_mutex);
    if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) {
+      LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
       return CRYPT_INVALID_CIPHER;
    }
+   LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
    return CRYPT_OK;
 }
 

+ 3 - 0
src/misc/crypt/crypt_find_cipher.c

@@ -24,11 +24,14 @@ int find_cipher(const char *name)
 {
    int x;
    LTC_ARGCHK(name != NULL);
+   LTC_MUTEX_LOCK(&ltc_cipher_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) {
+          LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
           return x;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
    return -1;
 }
 

+ 3 - 0
src/misc/crypt/crypt_find_cipher_any.c

@@ -31,14 +31,17 @@ int find_cipher_any(const char *name, int blocklen, int keylen)
    x = find_cipher(name);
    if (x != -1) return x;
 
+   LTC_MUTEX_LOCK(&ltc_cipher_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].name == NULL) {
           continue;
        }
        if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) {
+          LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
           return x;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
    return -1;
 }
 

+ 5 - 1
src/misc/crypt/crypt_find_cipher_id.c

@@ -23,11 +23,15 @@
 int find_cipher_id(unsigned char ID)
 {
    int x;
+   LTC_MUTEX_LOCK(&ltc_cipher_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].ID == ID) {
-          return (cipher_descriptor[x].name == NULL) ? -1 : x;
+          x = (cipher_descriptor[x].name == NULL) ? -1 : x;
+          LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
+          return x;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
    return -1;
 }
 

+ 3 - 0
src/misc/crypt/crypt_find_hash.c

@@ -24,11 +24,14 @@ int find_hash(const char *name)
 {
    int x;
    LTC_ARGCHK(name != NULL);
+   LTC_MUTEX_LOCK(&ltc_hash_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (hash_descriptor[x].name != NULL && strcmp(hash_descriptor[x].name, name) == 0) {
+          LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
           return x;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
    return -1;
 }
 

+ 2 - 0
src/misc/crypt/crypt_find_hash_any.c

@@ -28,6 +28,7 @@
    x = find_hash(name);
    if (x != -1) return x;
 
+   LTC_MUTEX_LOCK(&ltc_hash_mutex);
    y = MAXBLOCKSIZE+1;
    z = -1;
    for (x = 0; x < TAB_SIZE; x++) {
@@ -39,6 +40,7 @@
           y = hash_descriptor[x].hashsize;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
    return z;
 }
 

+ 7 - 3
src/misc/crypt/crypt_find_hash_id.c

@@ -23,11 +23,15 @@
 int find_hash_id(unsigned char ID)
 {
    int x;
+   LTC_MUTEX_LOCK(&ltc_hash_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
-       if (hash_descriptor[x].ID == ID) {
-          return (hash_descriptor[x].name == NULL) ? -1 : x;
-       }
+      if (hash_descriptor[x].ID == ID) {
+          x = (hash_descriptor[x].name == NULL) ? -1 : x;
+          LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
+          return x;
+      }
    }
+   LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
    return -1;
 }
 

+ 3 - 0
src/misc/crypt/crypt_find_prng.c

@@ -24,11 +24,14 @@ int find_prng(const char *name)
 {
    int x;
    LTC_ARGCHK(name != NULL);
+   LTC_MUTEX_LOCK(&ltc_prng_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if ((prng_descriptor[x].name != NULL) && strcmp(prng_descriptor[x].name, name) == 0) {
+          LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
           return x;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
    return -1;
 }
 

+ 3 - 0
src/misc/crypt/crypt_hash_descriptor.c

@@ -19,6 +19,9 @@ struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = {
 { NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL }
 };
 
+LTC_MUTEX_GLOBAL(ltc_hash_mutex);
+
+
 /* $Source$ */
 /* $Revision$ */
 /* $Date$ */

+ 3 - 0
src/misc/crypt/crypt_hash_is_valid.c

@@ -22,9 +22,12 @@
 */
 int hash_is_valid(int idx)
 {
+   LTC_MUTEX_LOCK(&ltc_hash_mutex);
    if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
+      LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
       return CRYPT_INVALID_HASH;
    }
+   LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
    return CRYPT_OK;
 }
 

+ 3 - 0
src/misc/crypt/crypt_prng_descriptor.c

@@ -18,6 +18,9 @@ struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = {
 { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
+LTC_MUTEX_GLOBAL(ltc_prng_mutex);
+
+
 /* $Source$ */
 /* $Revision$ */
 /* $Date$ */

+ 3 - 0
src/misc/crypt/crypt_prng_is_valid.c

@@ -22,9 +22,12 @@
 */
 int prng_is_valid(int idx)
 {
+   LTC_MUTEX_LOCK(&ltc_prng_mutex);
    if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
+      LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
       return CRYPT_INVALID_PRNG;
    }
+   LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
    return CRYPT_OK;
 }
 

+ 4 - 0
src/misc/crypt/crypt_register_cipher.c

@@ -27,8 +27,10 @@ int register_cipher(const struct ltc_cipher_descriptor *cipher)
    LTC_ARGCHK(cipher != NULL);
 
    /* is it already registered? */
+   LTC_MUTEX_LOCK(&ltc_cipher_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) {
+          LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
           return x;
        }
    }
@@ -37,11 +39,13 @@ int register_cipher(const struct ltc_cipher_descriptor *cipher)
    for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].name == NULL) {
           XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor));
+          LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
           return x;
        }
    }
 
    /* no spot */
+   LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
    return -1;
 }
 

+ 4 - 0
src/misc/crypt/crypt_register_hash.c

@@ -27,8 +27,10 @@ int register_hash(const struct ltc_hash_descriptor *hash)
    LTC_ARGCHK(hash != NULL);
 
    /* is it already registered? */
+   LTC_MUTEX_LOCK(&ltc_hash_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (memcmp(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
+          LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
           return x;
        }
    }
@@ -37,11 +39,13 @@ int register_hash(const struct ltc_hash_descriptor *hash)
    for (x = 0; x < TAB_SIZE; x++) {
        if (hash_descriptor[x].name == NULL) {
           XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor));
+          LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
           return x;
        }
    }
 
    /* no spot */
+   LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
    return -1;
 }
 

+ 4 - 0
src/misc/crypt/crypt_register_prng.c

@@ -27,8 +27,10 @@ int register_prng(const struct ltc_prng_descriptor *prng)
    LTC_ARGCHK(prng != NULL);
 
    /* is it already registered? */
+   LTC_MUTEX_LOCK(&ltc_prng_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (memcmp(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {
+          LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
           return x;
        }
    }
@@ -37,11 +39,13 @@ int register_prng(const struct ltc_prng_descriptor *prng)
    for (x = 0; x < TAB_SIZE; x++) {
        if (prng_descriptor[x].name == NULL) {
           XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor));
+          LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
           return x;
        }
    }
 
    /* no spot */
+   LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
    return -1;
 }
 

+ 3 - 0
src/misc/crypt/crypt_unregister_cipher.c

@@ -27,13 +27,16 @@ int unregister_cipher(const struct ltc_cipher_descriptor *cipher)
    LTC_ARGCHK(cipher != NULL);
 
    /* is it already registered? */
+   LTC_MUTEX_LOCK(&ltc_cipher_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (memcmp(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) {
           cipher_descriptor[x].name = NULL;
           cipher_descriptor[x].ID   = 255;
+          LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
           return CRYPT_OK;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
    return CRYPT_ERROR;
 }
 

+ 3 - 0
src/misc/crypt/crypt_unregister_hash.c

@@ -27,12 +27,15 @@ int unregister_hash(const struct ltc_hash_descriptor *hash)
    LTC_ARGCHK(hash != NULL);
 
    /* is it already registered? */
+   LTC_MUTEX_LOCK(&ltc_hash_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (memcmp(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
           hash_descriptor[x].name = NULL;
+          LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
           return CRYPT_OK;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
    return CRYPT_ERROR;
 }
 

+ 4 - 1
src/misc/crypt/crypt_unregister_prng.c

@@ -25,14 +25,17 @@ int unregister_prng(const struct ltc_prng_descriptor *prng)
    int x;
 
    LTC_ARGCHK(prng != NULL);
-
+ 
    /* is it already registered? */
+   LTC_MUTEX_LOCK(&ltc_prng_mutex);
    for (x = 0; x < TAB_SIZE; x++) {
        if (memcmp(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) != 0) {
           prng_descriptor[x].name = NULL;
+          LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
           return CRYPT_OK;
        }
    }
+   LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
    return CRYPT_ERROR;
 }
 

+ 168 - 0
src/pk/asn1/der/choice/der_decode_choice.c

@@ -0,0 +1,168 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+  @file der_decode_choice.c
+  ASN.1 DER, decode a CHOICE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+   Decode a CHOICE
+   @param in       The DER encoded input
+   @param inlen    [in/out] The size of the input and resulting size of read type
+   @param list     The list of items to decode
+   @param outlen   The number of items in the list
+   @return CRYPT_OK on success
+*/
+int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
+                            ltc_asn1_list *list, unsigned long  outlen)
+{
+   unsigned long size, x, z;
+   void          *data;
+
+   LTC_ARGCHK(in    != NULL);
+   LTC_ARGCHK(inlen != NULL);
+   LTC_ARGCHK(list  != NULL);
+
+   /* get blk size */
+   if (*inlen < 2) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* set all of the "used" flags to zero */
+   for (x = 0; x < outlen; x++) {
+       list[x].used = 0;
+   }
+
+   /* now scan until we have a winner */
+   for (x = 0; x < outlen; x++) {
+       size = list[x].size;
+       data = list[x].data;
+
+       switch (list[x].type) {
+           case LTC_ASN1_INTEGER:
+               if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
+                  if (der_length_integer(data, &z) == CRYPT_OK) {
+                      list[x].used = 1;
+                      *inlen       = z;
+                      return CRYPT_OK;
+                  }
+               }
+               break;
+
+           case LTC_ASN1_SHORT_INTEGER:
+               if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
+                  if (der_length_short_integer(size, &z) == CRYPT_OK) {
+                      list[x].used = 1;
+                      *inlen       = z;
+                      return CRYPT_OK;
+                  }
+               }
+               break;
+
+           case LTC_ASN1_BIT_STRING:
+               if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
+                  if (der_length_bit_string(size, &z) == CRYPT_OK) {
+                     list[x].used = 1;
+                     list[x].size = size;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
+           case LTC_ASN1_OCTET_STRING:
+               if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
+                  if (der_length_octet_string(size, &z) == CRYPT_OK) {
+                     list[x].used = 1;
+                     list[x].size = size;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
+           case LTC_ASN1_NULL:
+               if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) {
+                  *inlen = 2;
+                  return CRYPT_OK;
+               }
+               break;
+                  
+           case LTC_ASN1_OBJECT_IDENTIFIER:
+               if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {
+                  if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {
+                     list[x].used = 1;
+                     list[x].size = size;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
+           case LTC_ASN1_IA5_STRING:
+               if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
+                  if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
+                     list[x].used = 1;
+                     list[x].size = size;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
+
+           case LTC_ASN1_PRINTABLE_STRING:
+               if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {
+                  if (der_length_printable_string(data, size, &z) == CRYPT_OK) {
+                     list[x].used = 1;
+                     list[x].size = size;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
+           case LTC_ASN1_UTCTIME:
+               z = *inlen;
+               if (der_decode_utctime(in, &z, data) == CRYPT_OK) {
+                  list[x].used = 1;
+                  *inlen       = z;
+                  return CRYPT_OK;
+               }
+               break;
+
+           case LTC_ASN1_SEQUENCE:
+               if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {
+                  if (der_length_sequence(data, size, &z) == CRYPT_OK) {
+                     list[x].used = 1;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
+           default:
+               return CRYPT_INVALID_ARG;
+       }
+   }
+
+   return CRYPT_INVALID_PACKET;
+}
+
+#endif
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */

+ 19 - 0
src/pk/asn1/der/sequence/der_decode_sequence.c

@@ -185,6 +185,15 @@ int der_decode_sequence(const unsigned char *in,   unsigned long  inlen,
                inlen -= z;
                break;
 
+           case LTC_ASN1_UTCTIME:
+               z = inlen;
+               if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
+                  goto LBL_ERR;
+               }
+               x     += z;
+               inlen -= z;
+               break;
+
            case LTC_ASN1_SEQUENCE:
                z = inlen;
                if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
@@ -197,6 +206,16 @@ int der_decode_sequence(const unsigned char *in,   unsigned long  inlen,
                inlen -= z;
                break;
 
+
+           case LTC_ASN1_CHOICE:
+               z = inlen;
+               if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
+                  goto LBL_ERR;
+               }
+               x     += z;
+               inlen -= z;
+               break;
+
            default:
                err = CRYPT_INVALID_ARG;
                goto LBL_ERR;

+ 4 - 0
src/pk/asn1/der/sequence/der_decode_sequence_multi.c

@@ -50,7 +50,9 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
            case LTC_ASN1_OBJECT_IDENTIFIER:
            case LTC_ASN1_IA5_STRING:
            case LTC_ASN1_PRINTABLE_STRING:
+           case LTC_ASN1_UTCTIME:
            case LTC_ASN1_SEQUENCE:
+           case LTC_ASN1_CHOICE:
                 ++x; 
                 break;
           
@@ -92,7 +94,9 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
            case LTC_ASN1_OBJECT_IDENTIFIER:
            case LTC_ASN1_IA5_STRING:
            case LTC_ASN1_PRINTABLE_STRING:
+           case LTC_ASN1_UTCTIME:
            case LTC_ASN1_SEQUENCE:
+           case LTC_ASN1_CHOICE:
                 list[x].type   = type;
                 list[x].size   = size;
                 list[x++].data = data;

+ 16 - 0
src/pk/asn1/der/sequence/der_encode_sequence.c

@@ -103,6 +103,13 @@ int der_encode_sequence(ltc_asn1_list *list, unsigned long inlen,
                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_SEQUENCE:
                if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
                   goto LBL_ERR;
@@ -241,6 +248,15 @@ int der_encode_sequence(ltc_asn1_list *list, unsigned long inlen,
                *outlen -= z;
                break;
 
+           case LTC_ASN1_UTCTIME:
+               z = *outlen;
+               if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
+                  goto LBL_ERR;
+               }
+               x       += z;
+               *outlen -= z;
+               break;
+
            case LTC_ASN1_SEQUENCE:
                z = *outlen;
                if ((err = der_encode_sequence(data, size, out + x, &z)) != CRYPT_OK) {

+ 2 - 0
src/pk/asn1/der/sequence/der_encode_sequence_multi.c

@@ -51,6 +51,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
            case LTC_ASN1_OBJECT_IDENTIFIER:
            case LTC_ASN1_IA5_STRING:
            case LTC_ASN1_PRINTABLE_STRING:
+           case LTC_ASN1_UTCTIME:
            case LTC_ASN1_SEQUENCE:
                 ++x; 
                 break;
@@ -93,6 +94,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
            case LTC_ASN1_OBJECT_IDENTIFIER:
            case LTC_ASN1_IA5_STRING:
            case LTC_ASN1_PRINTABLE_STRING:
+           case LTC_ASN1_UTCTIME:
            case LTC_ASN1_SEQUENCE:
                 list[x].type   = type;
                 list[x].size   = size;

+ 120 - 0
src/pk/asn1/der/utctime/der_decode_utctime.c

@@ -0,0 +1,120 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+  @file der_decode_utctime.c
+  ASN.1 DER, decode a  UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static int char_to_int(unsigned char x)
+{
+   switch (x)  {
+      case '0': return 0;
+      case '1': return 1;
+      case '2': return 2;
+      case '3': return 3;
+      case '4': return 4;
+      case '5': return 5;
+      case '6': return 6;
+      case '7': return 7;
+      case '8': return 8;
+      case '9': return 9;
+   }
+   return 100;
+}
+
+#define DECODE_V(y, max) \
+   y  = char_to_int(buf[x])*10 + char_to_int(buf[x+1]); \
+   if (y >= max) return CRYPT_INVALID_PACKET;           \
+   x += 2;
+
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+                             ltc_utctime   *out)
+{
+   unsigned char buf[32];
+   unsigned long x;
+   int           y;
+
+   LTC_ARGCHK(in    != NULL);
+   LTC_ARGCHK(inlen != NULL);
+   LTC_ARGCHK(out   != NULL);
+
+   /* check header */
+   if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* decode the string */
+   for (x = 0; x < in[1]; x++) {
+       y = der_ia5_value_decode(in[x+2]);
+       if (y == -1) {
+          return CRYPT_INVALID_PACKET;
+       }
+       buf[x] = y;
+   }
+   *inlen = 2 + x;
+
+
+   /* possible encodings are 
+YYMMDDhhmmZ
+YYMMDDhhmm+hh'mm'
+YYMMDDhhmm-hh'mm'
+YYMMDDhhmmssZ
+YYMMDDhhmmss+hh'mm'
+YYMMDDhhmmss-hh'mm'
+
+    So let's do a trivial decode upto [including] mm 
+   */
+
+    x = 0;
+    DECODE_V(out->YY, 100);
+    DECODE_V(out->MM, 13);
+    DECODE_V(out->DD, 32);
+    DECODE_V(out->hh, 24);
+    DECODE_V(out->mm, 60);
+
+    /* clear timezone and seconds info */
+    out->off_dir = out->off_hh = out->off_mm = out->ss = 0;
+
+    /* now is it Z, +, - or 0-9 */
+    if (buf[x] == 'Z') {
+       return CRYPT_OK;
+    } else if (buf[x] == '+' || buf[x] == '-') {
+       out->off_dir = (buf[x++] == '+') ? 0 : 1;
+       DECODE_V(out->off_hh, 24);
+       DECODE_V(out->off_mm, 60);
+       return CRYPT_OK;
+    }
+
+    /* decode seconds */
+    DECODE_V(out->ss, 60);
+
+    /* now is it Z, +, - */
+    if (buf[x] == 'Z') {
+       return CRYPT_OK;
+    } else if (buf[x] == '+' || buf[x] == '-') {
+       out->off_dir = (buf[x++] == '+') ? 0 : 1;
+       DECODE_V(out->off_hh, 24);
+       DECODE_V(out->off_mm, 60);
+       return CRYPT_OK;
+    } else {
+       return CRYPT_INVALID_PACKET;
+    }
+}
+
+#endif
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */

+ 80 - 0
src/pk/asn1/der/utctime/der_encode_utctime.c

@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+  @file der_encode_utctime.c
+  ASN.1 DER, encode a  UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const char *baseten = "0123456789";
+
+#define STORE_V(y) \
+    out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \
+    out[x++] = der_ia5_char_encode(baseten[y % 10]);
+
+/**
+  Gets length of DER encoding of UTCTIME
+  @param outlen [out] The length of the DER encoding
+  @return CRYPT_OK if successful
+*/
+int der_encode_utctime(ltc_utctime *utctime, 
+                       unsigned char *out,   unsigned long *outlen)
+{
+    unsigned long x, tmplen;
+    int           err;
+ 
+    LTC_ARGCHK(utctime != NULL);
+    LTC_ARGCHK(out     != NULL);
+    LTC_ARGCHK(outlen  != NULL);
+
+    if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) {
+       return err;
+    }
+    if (tmplen > *outlen) {
+        return CRYPT_BUFFER_OVERFLOW;
+    }
+    
+    /* store header */
+    out[0] = 0x17;
+
+    /* store values */
+    x = 2;
+    STORE_V(utctime->YY);
+    STORE_V(utctime->MM);
+    STORE_V(utctime->DD);
+    STORE_V(utctime->hh);
+    STORE_V(utctime->mm);
+    STORE_V(utctime->ss);
+
+    if (utctime->off_mm || utctime->off_hh) {
+       out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+');
+       STORE_V(utctime->off_hh);
+       STORE_V(utctime->off_mm);
+    } else {
+       out[x++] = der_ia5_char_encode('Z');
+    }
+
+    /* store length */
+    out[1] = x - 2;
+   
+    /* all good let's return */
+    *outlen = x;
+    return CRYPT_OK;
+}
+
+#endif
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */

+ 45 - 0
src/pk/asn1/der/utctime/der_length_utctime.c

@@ -0,0 +1,45 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+  @file der_length_utctime.c
+  ASN.1 DER, get length of UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+  Gets length of DER encoding of UTCTIME
+  @param outlen [out] The length of the DER encoding
+  @return CRYPT_OK if successful
+*/
+int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen)
+{
+   LTC_ARGCHK(outlen  != NULL);
+   LTC_ARGCHK(utctime != NULL);
+
+   if (utctime->off_hh == 0 && utctime->off_mm == 0) {
+      /* we encode as YYMMDDhhmmssZ */
+      *outlen = 2 + 13;
+   } else {
+      /* we encode as YYMMDDhhmmss{+|-}hh'mm' */
+      *outlen = 2 + 17;
+   }
+
+   return CRYPT_OK;
+}
+
+#endif
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */

+ 1 - 1
src/pk/pkcs1/pkcs_1_oaep_decode.c

@@ -160,7 +160,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg,    unsigned long msglen,
 
    /* copy message */
    *outlen = (modulus_len - hLen - 1) - x;
-   XMEMCPY(out, DB + x, modulus_len - hLen - 1);
+   XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);
    x += modulus_len - hLen - 1;
 
    /* valid packet */

+ 6 - 0
src/pk/rsa/rsa_exptmod.c

@@ -86,6 +86,12 @@ int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
       err = CRYPT_BUFFER_OVERFLOW;
       goto done;
    }
+
+   /* this should never happen ... */
+   if (mp_unsigned_bin_size(&tmp) > mp_unsigned_bin_size(&key->N)) {
+      err = CRYPT_ERROR;
+      goto done;
+   }
    *outlen = x;
 
    /* convert it */

+ 141 - 1
testprof/der_tests.c

@@ -10,6 +10,64 @@ int der_tests(void)
 
 #else
 
+static int der_choice_test(void)
+{
+   ltc_asn1_list types[7], host[1];
+   unsigned char bitbuf[10], octetbuf[10], ia5buf[10], printbuf[10], outbuf[256];
+   unsigned long integer, oidbuf[10], outlen, inlen, x, y;
+   mp_int        mpinteger;
+   ltc_utctime   utctime = { 91, 5, 6, 16, 45, 40, 1, 7, 0 };
+
+   /* setup variables */
+   for (x = 0; x < sizeof(bitbuf); x++)   { bitbuf[x]   = x & 1; }
+   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';   }
+   integer = 1;
+   for (x = 0; x < sizeof(oidbuf)/sizeof(oidbuf[0]); x++)   { oidbuf[x] = x + 1;   }
+   DO(mpi_to_ltc_error(mp_init(&mpinteger)));
+
+   for (x = 0; x < 14; 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);
+       } else {
+          LTC_SET_ASN1(types, 4, LTC_ASN1_INTEGER, &mpinteger, 1);
+       }
+       LTC_SET_ASN1(types, 5, LTC_ASN1_OBJECT_IDENTIFIER, oidbuf, sizeof(oidbuf)/sizeof(oidbuf[0]));
+       LTC_SET_ASN1(types, 6, LTC_ASN1_UTCTIME, &utctime, 1);
+
+       LTC_SET_ASN1(host, 0, LTC_ASN1_CHOICE, types, 7);
+
+       
+       /* encode */
+       outlen = sizeof(outbuf);
+       DO(der_encode_sequence(&types[x>6?x-7:x], 1, outbuf, &outlen));
+
+       /* decode it */
+       inlen = outlen;
+       DO(der_decode_sequence(outbuf, inlen, &host, 1));
+
+       for (y = 0; y < 7; y++) {
+           if (types[y].used && y != (x>6?x-7:x)) {
+               fprintf(stderr, "CHOICE, flag %lu in trial %lu was incorrectly set to one\n", y, x);
+               return 1;
+           }
+           if (!types[y].used && y == (x>6?x-7:x)) {
+               fprintf(stderr, "CHOICE, flag %lu in trial %lu was incorrectly set to zero\n", y, x);
+               return 1;
+           }
+      }
+  }
+  mp_clear(&mpinteger);
+  return 0;
+}
+   
+
 int der_tests(void)
 {
    unsigned long x, y, z, zz, oid[2][32];
@@ -27,6 +85,13 @@ int der_tests(void)
    static const unsigned char rsa_printable_der[] = { 0x13, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 
                                                       0x73, 0x65, 0x72, 0x20, 0x31 };
 
+   static const ltc_utctime   rsa_time1 = { 91, 5, 6, 16, 45, 40, 1, 7, 0 };
+   static const ltc_utctime   rsa_time2 = { 91, 5, 6, 23, 45, 40, 0, 0, 0 };
+   ltc_utctime                tmp_time;
+
+   static const unsigned char rsa_time1_der[] = { 0x17, 0x11, 0x39, 0x31, 0x30, 0x35, 0x30, 0x36, 0x31, 0x36, 0x34, 0x35, 0x34, 0x30, 0x2D, 0x30, 0x37, 0x30, 0x30 };
+   static const unsigned char rsa_time2_der[] = { 0x17, 0x0d, 0x39, 0x31, 0x30, 0x35, 0x30, 0x36, 0x32, 0x33, 0x34, 0x35, 0x34, 0x30, 0x5a };
+
    DO(mpi_to_ltc_error(mp_init_multi(&a, &b, &c, &d, &e, &f, &g, NULL)));
    for (zz = 0; zz < 16; zz++) {
       for (z = 0; z < 1024; z++) {
@@ -199,6 +264,11 @@ int der_tests(void)
       fprintf(stderr, "IA5 encode failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_ia5_der));
       return 1;
    }
+   DO(der_length_ia5_string(rsa_ia5, strlen(rsa_ia5), &y));
+   if (y != x) {
+      fprintf(stderr, "IA5 length failed to match: %lu, %lu\n", x, y);
+      return 1;
+   }
    y = sizeof(buf[1]);
    DO(der_decode_ia5_string(buf[0], x, buf[1], &y));
    if (y != strlen(rsa_ia5) || memcmp(buf[1], rsa_ia5, strlen(rsa_ia5))) {
@@ -213,6 +283,11 @@ int der_tests(void)
       fprintf(stderr, "PRINTABLE encode failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_printable_der));
       return 1;
    }
+   DO(der_length_printable_string(rsa_printable, strlen(rsa_printable), &y));
+   if (y != x) {
+      fprintf(stderr, "printable length failed to match: %lu, %lu\n", x, y);
+      return 1;
+   }
    y = sizeof(buf[1]);
    DO(der_decode_printable_string(buf[0], x, buf[1], &y));
    if (y != strlen(rsa_printable) || memcmp(buf[1], rsa_printable, strlen(rsa_printable))) {
@@ -220,7 +295,72 @@ int der_tests(void)
        return 1;
    }
 
-   return 0;
+/* Test UTC time */
+   x = sizeof(buf[0]);
+   DO(der_encode_utctime(&rsa_time1, buf[0], &x));
+   if (x != sizeof(rsa_time1_der) || memcmp(buf[0], rsa_time1_der, x)) {
+      fprintf(stderr, "UTCTIME encode of rsa_time1 failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_time1_der));
+fprintf(stderr, "\n\n");
+for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); printf("\n");
+
+      return 1;
+   }
+   DO(der_length_utctime(&rsa_time1, &y));
+   if (y != x) {
+      fprintf(stderr, "UTCTIME length failed to match for rsa_time1: %lu, %lu\n", x, y);
+      return 1;
+   }
+   DO(der_decode_utctime(buf[0], &y, &tmp_time));
+   if (y != x || memcmp(&rsa_time1, &tmp_time, sizeof(ltc_utctime))) {
+      fprintf(stderr, "UTCTIME decode failed for rsa_time1: %lu %lu\n", x, y);
+fprintf(stderr, "\n\n%u %u %u %u %u %u %u %u %u\n\n", 
+tmp_time.YY,
+tmp_time.MM,
+tmp_time.DD,
+tmp_time.hh,
+tmp_time.mm,
+tmp_time.ss,
+tmp_time.off_dir,
+tmp_time.off_mm,
+tmp_time.off_hh);
+      return 1;
+   }
+
+   x = sizeof(buf[0]);
+   DO(der_encode_utctime(&rsa_time2, buf[0], &x));
+   if (x != sizeof(rsa_time2_der) || memcmp(buf[0], rsa_time2_der, x)) {
+      fprintf(stderr, "UTCTIME encode of rsa_time2 failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_time1_der));
+fprintf(stderr, "\n\n");
+for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); printf("\n");
+
+      return 1;
+   }
+   DO(der_length_utctime(&rsa_time2, &y));
+   if (y != x) {
+      fprintf(stderr, "UTCTIME length failed to match for rsa_time2: %lu, %lu\n", x, y);
+      return 1;
+   }
+   DO(der_decode_utctime(buf[0], &y, &tmp_time));
+   if (y != x || memcmp(&rsa_time2, &tmp_time, sizeof(ltc_utctime))) {
+      fprintf(stderr, "UTCTIME decode failed for rsa_time2: %lu %lu\n", x, y);
+fprintf(stderr, "\n\n%u %u %u %u %u %u %u %u %u\n\n", 
+tmp_time.YY,
+tmp_time.MM,
+tmp_time.DD,
+tmp_time.hh,
+tmp_time.mm,
+tmp_time.ss,
+tmp_time.off_dir,
+tmp_time.off_mm,
+tmp_time.off_hh);
+
+
+      return 1;
+   }
+
+
+
+   return der_choice_test();
 }
 
 #endif