diff --git a/Doxyfile b/Doxyfile index fc6d509..a8de8a9 100644 --- a/Doxyfile +++ b/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. diff --git a/TODO b/TODO index 828e094..f4f0665 100644 --- a/TODO +++ b/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 diff --git a/build.sh b/build.sh index 6867c2a..a018aac 100644 --- a/build.sh +++ b/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 $ diff --git a/changes b/changes index bc943a8..65ccd16 100644 --- a/changes +++ b/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 $ */ diff --git a/crypt.tex b/crypt.tex index 3342666..cf1c37e 100644 --- a/crypt.tex +++ b/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 \\ \\ tomstdenis@gmail.com \\ @@ -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 $ diff --git a/demos/test.c b/demos/test.c index b1e3966..750025e 100644 --- a/demos/test.c +++ b/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); diff --git a/doc/crypt.pdf b/doc/crypt.pdf index 03c54cf..1c56c51 100644 Binary files a/doc/crypt.pdf and b/doc/crypt.pdf differ diff --git a/makefile b/makefile index f719cea..fba5f73 100644 --- a/makefile +++ b/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 $ diff --git a/makefile.icc b/makefile.icc index e7fcc1a..a9ab38f 100644 --- a/makefile.icc +++ b/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 $ diff --git a/makefile.msvc b/makefile.msvc index 9db1e8f..ae01079 100644 --- a/makefile.msvc +++ b/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 $ diff --git a/makefile.shared b/makefile.shared index fb68a23..62cc87b 100644 --- a/makefile.shared +++ b/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 $ diff --git a/notes/tech0006.txt b/notes/tech0006.txt new file mode 100644 index 0000000..ecbe8b0 --- /dev/null +++ b/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 $ diff --git a/src/headers/tomcrypt.h b/src/headers/tomcrypt.h index c072ef5..43c4b34 100644 --- a/src/headers/tomcrypt.h +++ b/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 diff --git a/src/headers/tomcrypt_cipher.h b/src/headers/tomcrypt_cipher.h index d162a2a..793ba6a 100644 --- a/src/headers/tomcrypt_cipher.h +++ b/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$ */ diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index abf5bc2..c63197b 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -229,6 +229,28 @@ #endif +/* THREAD management */ + +#ifdef LTC_PTHREAD + +#include + +#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$ */ diff --git a/src/headers/tomcrypt_hash.h b/src/headers/tomcrypt_hash.h index f92f2d6..1a39ad1 100644 --- a/src/headers/tomcrypt_hash.h +++ b/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); diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index 08b16ff..bb9707e 100644 --- a/src/headers/tomcrypt_pk.h +++ b/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$ */ diff --git a/src/headers/tomcrypt_prng.h b/src/headers/tomcrypt_prng.h index a257f4c..b4655f3 100644 --- a/src/headers/tomcrypt_prng.h +++ b/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 diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index 99c07a8..718c1f7 100644 --- a/src/misc/crypt/crypt.c +++ b/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" diff --git a/src/misc/crypt/crypt_cipher_descriptor.c b/src/misc/crypt/crypt_cipher_descriptor.c index a255ec6..7dce782 100644 --- a/src/misc/crypt/crypt_cipher_descriptor.c +++ b/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$ */ diff --git a/src/misc/crypt/crypt_cipher_is_valid.c b/src/misc/crypt/crypt_cipher_is_valid.c index d5db7bc..f56dd80 100644 --- a/src/misc/crypt/crypt_cipher_is_valid.c +++ b/src/misc/crypt/crypt_cipher_is_valid.c @@ -22,9 +22,12 @@ */ int cipher_is_valid(int idx) { + LTC_MUTEX_LOCK(<c_cipher_mutex); if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_INVALID_CIPHER; } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_OK; } diff --git a/src/misc/crypt/crypt_find_cipher.c b/src/misc/crypt/crypt_find_cipher.c index 230b908..04d40da 100644 --- a/src/misc/crypt/crypt_find_cipher.c +++ b/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(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; } diff --git a/src/misc/crypt/crypt_find_cipher_any.c b/src/misc/crypt/crypt_find_cipher_any.c index fe669f3..ab9dae9 100644 --- a/src/misc/crypt/crypt_find_cipher_any.c +++ b/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(<c_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(<c_cipher_mutex); return x; } } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; } diff --git a/src/misc/crypt/crypt_find_cipher_id.c b/src/misc/crypt/crypt_find_cipher_id.c index 766fb01..e0171e3 100644 --- a/src/misc/crypt/crypt_find_cipher_id.c +++ b/src/misc/crypt/crypt_find_cipher_id.c @@ -23,11 +23,15 @@ int find_cipher_id(unsigned char ID) { int x; + LTC_MUTEX_LOCK(<c_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(<c_cipher_mutex); + return x; } } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; } diff --git a/src/misc/crypt/crypt_find_hash.c b/src/misc/crypt/crypt_find_hash.c index c580103..1b526c9 100644 --- a/src/misc/crypt/crypt_find_hash.c +++ b/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(<c_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(<c_hash_mutex); return x; } } + LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; } diff --git a/src/misc/crypt/crypt_find_hash_any.c b/src/misc/crypt/crypt_find_hash_any.c index 98c277e..113c96b 100644 --- a/src/misc/crypt/crypt_find_hash_any.c +++ b/src/misc/crypt/crypt_find_hash_any.c @@ -28,6 +28,7 @@ x = find_hash(name); if (x != -1) return x; + LTC_MUTEX_LOCK(<c_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(<c_hash_mutex); return z; } diff --git a/src/misc/crypt/crypt_find_hash_id.c b/src/misc/crypt/crypt_find_hash_id.c index 7c23864..527c768 100644 --- a/src/misc/crypt/crypt_find_hash_id.c +++ b/src/misc/crypt/crypt_find_hash_id.c @@ -23,11 +23,15 @@ int find_hash_id(unsigned char ID) { int x; + LTC_MUTEX_LOCK(<c_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(<c_hash_mutex); + return x; + } } + LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; } diff --git a/src/misc/crypt/crypt_find_prng.c b/src/misc/crypt/crypt_find_prng.c index 554083e..d803722 100644 --- a/src/misc/crypt/crypt_find_prng.c +++ b/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(<c_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(<c_prng_mutex); return x; } } + LTC_MUTEX_UNLOCK(<c_prng_mutex); return -1; } diff --git a/src/misc/crypt/crypt_hash_descriptor.c b/src/misc/crypt/crypt_hash_descriptor.c index 969ff83..979e2c4 100644 --- a/src/misc/crypt/crypt_hash_descriptor.c +++ b/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$ */ diff --git a/src/misc/crypt/crypt_hash_is_valid.c b/src/misc/crypt/crypt_hash_is_valid.c index 103f71b..725af48 100644 --- a/src/misc/crypt/crypt_hash_is_valid.c +++ b/src/misc/crypt/crypt_hash_is_valid.c @@ -22,9 +22,12 @@ */ int hash_is_valid(int idx) { + LTC_MUTEX_LOCK(<c_hash_mutex); if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_INVALID_HASH; } + LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_OK; } diff --git a/src/misc/crypt/crypt_prng_descriptor.c b/src/misc/crypt/crypt_prng_descriptor.c index 8b8ad34..e269502 100644 --- a/src/misc/crypt/crypt_prng_descriptor.c +++ b/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$ */ diff --git a/src/misc/crypt/crypt_prng_is_valid.c b/src/misc/crypt/crypt_prng_is_valid.c index f8ccbcf..815b03a 100644 --- a/src/misc/crypt/crypt_prng_is_valid.c +++ b/src/misc/crypt/crypt_prng_is_valid.c @@ -22,9 +22,12 @@ */ int prng_is_valid(int idx) { + LTC_MUTEX_LOCK(<c_prng_mutex); if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_INVALID_PRNG; } + LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_OK; } diff --git a/src/misc/crypt/crypt_register_cipher.c b/src/misc/crypt/crypt_register_cipher.c index 4fea824..7701d3c 100644 --- a/src/misc/crypt/crypt_register_cipher.c +++ b/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(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { + LTC_MUTEX_UNLOCK(<c_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(<c_cipher_mutex); return x; } } /* no spot */ + LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; } diff --git a/src/misc/crypt/crypt_register_hash.c b/src/misc/crypt/crypt_register_hash.c index 3ece4f7..4e24dd1 100644 --- a/src/misc/crypt/crypt_register_hash.c +++ b/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(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (memcmp(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { + LTC_MUTEX_UNLOCK(<c_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(<c_hash_mutex); return x; } } /* no spot */ + LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; } diff --git a/src/misc/crypt/crypt_register_prng.c b/src/misc/crypt/crypt_register_prng.c index 59eb456..4689be3 100644 --- a/src/misc/crypt/crypt_register_prng.c +++ b/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(<c_prng_mutex); for (x = 0; x < TAB_SIZE; x++) { if (memcmp(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) { + LTC_MUTEX_UNLOCK(<c_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(<c_prng_mutex); return x; } } /* no spot */ + LTC_MUTEX_UNLOCK(<c_prng_mutex); return -1; } diff --git a/src/misc/crypt/crypt_unregister_cipher.c b/src/misc/crypt/crypt_unregister_cipher.c index f8fdac9..5d09175 100644 --- a/src/misc/crypt/crypt_unregister_cipher.c +++ b/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(<c_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(<c_cipher_mutex); return CRYPT_OK; } } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_ERROR; } diff --git a/src/misc/crypt/crypt_unregister_hash.c b/src/misc/crypt/crypt_unregister_hash.c index 51f3eac..6fa12b7 100644 --- a/src/misc/crypt/crypt_unregister_hash.c +++ b/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(<c_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(<c_hash_mutex); return CRYPT_OK; } } + LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_ERROR; } diff --git a/src/misc/crypt/crypt_unregister_prng.c b/src/misc/crypt/crypt_unregister_prng.c index 5e90832..331a90a 100644 --- a/src/misc/crypt/crypt_unregister_prng.c +++ b/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(<c_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(<c_prng_mutex); return CRYPT_OK; } } + LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_ERROR; } diff --git a/src/pk/asn1/der/choice/der_decode_choice.c b/src/pk/asn1/der/choice/der_decode_choice.c new file mode 100644 index 0000000..6eddf23 --- /dev/null +++ b/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, tomstdenis@gmail.com, 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$ */ diff --git a/src/pk/asn1/der/sequence/der_decode_sequence.c b/src/pk/asn1/der/sequence/der_decode_sequence.c index 7228497..5837dc8 100644 --- a/src/pk/asn1/der/sequence/der_decode_sequence.c +++ b/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; diff --git a/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/src/pk/asn1/der/sequence/der_decode_sequence_multi.c index 539f310..4e4a8b2 100644 --- a/src/pk/asn1/der/sequence/der_decode_sequence_multi.c +++ b/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; diff --git a/src/pk/asn1/der/sequence/der_encode_sequence.c b/src/pk/asn1/der/sequence/der_encode_sequence.c index 6f86a4a..d53153c 100644 --- a/src/pk/asn1/der/sequence/der_encode_sequence.c +++ b/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) { diff --git a/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/src/pk/asn1/der/sequence/der_encode_sequence_multi.c index 1b7fccb..0aa52e7 100644 --- a/src/pk/asn1/der/sequence/der_encode_sequence_multi.c +++ b/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; diff --git a/src/pk/asn1/der/utctime/der_decode_utctime.c b/src/pk/asn1/der/utctime/der_decode_utctime.c new file mode 100644 index 0000000..45e60a5 --- /dev/null +++ b/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, tomstdenis@gmail.com, 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$ */ diff --git a/src/pk/asn1/der/utctime/der_encode_utctime.c b/src/pk/asn1/der/utctime/der_encode_utctime.c new file mode 100644 index 0000000..12c184f --- /dev/null +++ b/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, tomstdenis@gmail.com, 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$ */ diff --git a/src/pk/asn1/der/utctime/der_length_utctime.c b/src/pk/asn1/der/utctime/der_length_utctime.c new file mode 100644 index 0000000..57ccd65 --- /dev/null +++ b/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, tomstdenis@gmail.com, 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$ */ diff --git a/src/pk/pkcs1/pkcs_1_oaep_decode.c b/src/pk/pkcs1/pkcs_1_oaep_decode.c index fd368e6..97b84ba 100644 --- a/src/pk/pkcs1/pkcs_1_oaep_decode.c +++ b/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 */ diff --git a/src/pk/rsa/rsa_exptmod.c b/src/pk/rsa/rsa_exptmod.c index b7bfebd..565ad3d 100644 --- a/src/pk/rsa/rsa_exptmod.c +++ b/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 */ diff --git a/testprof/der_tests.c b/testprof/der_tests.c index 95f3348..e50044d 100644 --- a/testprof/der_tests.c +++ b/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