summaryrefslogtreecommitdiffhomepage
path: root/libtomcrypt/src/pk
diff options
context:
space:
mode:
Diffstat (limited to 'libtomcrypt/src/pk')
-rw-r--r--libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c101
-rw-r--r--libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c87
-rw-r--r--libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c54
-rw-r--r--libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c168
-rw-r--r--libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c95
-rw-r--r--libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c84
-rw-r--r--libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c194
-rw-r--r--libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c110
-rw-r--r--libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c128
-rw-r--r--libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c81
-rw-r--r--libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c99
-rw-r--r--libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c103
-rw-r--r--libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c84
-rw-r--r--libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c90
-rw-r--r--libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c85
-rw-r--r--libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c53
-rw-r--r--libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c95
-rw-r--r--libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c84
-rw-r--r--libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c166
-rw-r--r--libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence.c234
-rw-r--r--libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c124
-rw-r--r--libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence.c281
-rw-r--r--libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c123
-rw-r--r--libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c144
-rw-r--r--libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c68
-rw-r--r--libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c97
-rw-r--r--libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c69
-rw-r--r--libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c120
-rw-r--r--libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c80
-rw-r--r--libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c45
-rw-r--r--libtomcrypt/src/pk/dh/dh.c524
-rw-r--r--libtomcrypt/src/pk/dh/dh_sys.c499
-rw-r--r--libtomcrypt/src/pk/dsa/dsa_export.c72
-rw-r--r--libtomcrypt/src/pk/dsa/dsa_free.c34
-rw-r--r--libtomcrypt/src/pk/dsa/dsa_import.c89
-rw-r--r--libtomcrypt/src/pk/dsa/dsa_make_key.c146
-rw-r--r--libtomcrypt/src/pk/dsa/dsa_sign_hash.c159
-rw-r--r--libtomcrypt/src/pk/dsa/dsa_verify_hash.c128
-rw-r--r--libtomcrypt/src/pk/dsa/dsa_verify_key.c102
-rw-r--r--libtomcrypt/src/pk/ecc/ecc.c1036
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_sys.c462
-rw-r--r--libtomcrypt/src/pk/packet_store_header.c33
-rw-r--r--libtomcrypt/src/pk/packet_valid_header.c41
-rw-r--r--libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c55
-rw-r--r--libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c108
-rw-r--r--libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c188
-rw-r--r--libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c172
-rw-r--r--libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c41
-rw-r--r--libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c177
-rw-r--r--libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c174
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_decrypt_key.c93
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_encrypt_key.c80
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_export.c76
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_exptmod.c115
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_free.c35
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_import.c92
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_make_key.c125
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_sign_hash.c79
-rw-r--r--libtomcrypt/src/pk/rsa/rsa_verify_hash.c86
59 files changed, 8367 insertions, 0 deletions
diff --git a/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c b/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c
new file mode 100644
index 0000000..da5b989
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c
@@ -0,0 +1,101 @@
+/* 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_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a BIT STRING
+ @param in The DER encoded BIT STRING
+ @param inlen The size of the DER BIT STRING
+ @param out [out] The array of bits stored (one per char)
+ @param outlen [in/out] The number of bits stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long dlen, blen, x, y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* packet must be at least 4 bytes */
+ if (inlen < 4) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* check for 0x03 */
+ if ((in[0]&0x1F) != 0x03) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* offset in the data */
+ x = 1;
+
+ /* get the length of the data */
+ if (in[x] & 0x80) {
+ /* long format get number of length bytes */
+ y = in[x++] & 127;
+
+ /* invalid if 0 or > 2 */
+ if (y == 0 || y > 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data len */
+ dlen = 0;
+ while (y--) {
+ dlen = (dlen << 8) | (unsigned long)in[x++];
+ }
+ } else {
+ /* short format */
+ dlen = in[x++] & 127;
+ }
+
+ /* is the data len too long or too short? */
+ if ((dlen == 0) || (dlen + x > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get padding count */
+ blen = ((dlen - 1) << 3) - (in[x++] & 7);
+
+ /* too many bits? */
+ if (blen > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode/store the bits */
+ for (y = 0; y < blen; y++) {
+ out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0;
+ if ((y & 7) == 7) {
+ ++x;
+ }
+ }
+
+ /* we done */
+ *outlen = blen;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c b/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c
new file mode 100644
index 0000000..569c15b
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c
@@ -0,0 +1,87 @@
+/* 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_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a BIT STRING
+ @param in The array of bits to store (one per char)
+ @param inlen The number of bits tostore
+ @param out [out] The destination for the DER encoded BIT STRING
+ @param outlen [in/out] The max size and resulting size of the DER BIT STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y, buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* avoid overflows */
+ if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header (include bit padding count in length) */
+ x = 0;
+ y = (inlen >> 3) + ((inlen&7) ? 1 : 0) + 1;
+
+ out[x++] = 0x03;
+ if (y < 128) {
+ out[x++] = y;
+ } else if (y < 256) {
+ out[x++] = 0x81;
+ out[x++] = y;
+ } else if (y < 65536) {
+ out[x++] = 0x82;
+ out[x++] = (y>>8)&255;
+ out[x++] = y&255;
+ }
+
+ /* store number of zero padding bits */
+ out[x++] = (8 - inlen) & 7;
+
+ /* store the bits in big endian format */
+ for (y = buf = 0; y < inlen; y++) {
+ buf |= (in[y] ? 1 : 0) << (7 - (y & 7));
+ if ((y & 7) == 7) {
+ out[x++] = buf;
+ buf = 0;
+ }
+ }
+ /* store last byte */
+ if (inlen & 7) {
+ out[x++] = buf;
+ }
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c b/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c
new file mode 100644
index 0000000..dd6ea6d
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c
@@ -0,0 +1,54 @@
+/* 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_bit_string.c
+ ASN.1 DER, get length of BIT STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of BIT STRING
+ @param nbits The number of bits in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_bit_string(unsigned long nbits, unsigned long *outlen)
+{
+ unsigned long nbytes;
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the number of the bytes */
+ nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;
+
+ if (nbytes < 128) {
+ /* 03 LL PP DD DD DD ... */
+ *outlen = 2 + nbytes;
+ } else if (nbytes < 256) {
+ /* 03 81 LL PP DD DD DD ... */
+ *outlen = 3 + nbytes;
+ } else if (nbytes < 65536) {
+ /* 03 82 LL LL PP DD DD DD ... */
+ *outlen = 4 + nbytes;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c b/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c
new file mode 100644
index 0000000..61cba11
--- /dev/null
+++ b/libtomcrypt/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: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/06/19 11:25:01 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c b/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c
new file mode 100644
index 0000000..ac0a4af
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c
@@ -0,0 +1,95 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a IA5 STRING
+ @param in The DER encoded IA5 STRING
+ @param inlen The size of the DER IA5 STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x16 */
+ if ((in[0] & 0x1F) != 0x16) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_ia5_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c b/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c
new file mode 100644
index 0000000..a79b46e
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c
@@ -0,0 +1,84 @@
+/* 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_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store an IA5 STRING
+ @param in The array of IA5 to store (one per char)
+ @param inlen The number of IA5 to store
+ @param out [out] The destination for the DER encoded IA5 STRING
+ @param outlen [in/out] The max size and resulting size of the DER IA5 STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x16;
+ if (inlen < 128) {
+ out[x++] = inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (inlen>>8)&255;
+ out[x++] = inlen&255;
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (inlen>>16)&255;
+ out[x++] = (inlen>>8)&255;
+ out[x++] = inlen&255;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = der_ia5_char_encode(in[y]);
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c b/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c
new file mode 100644
index 0000000..d07d630
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c
@@ -0,0 +1,194 @@
+/* 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_ia5_string.c
+ ASN.1 DER, get length of IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} ia5_table[] = {
+{ '\0', 0 },
+{ '\a', 7 },
+{ '\b', 8 },
+{ '\t', 9 },
+{ '\n', 10 },
+{ '\f', 12 },
+{ '\r', 13 },
+{ ' ', 32 },
+{ '!', 33 },
+{ '"', 34 },
+{ '#', 35 },
+{ '$', 36 },
+{ '%', 37 },
+{ '&', 38 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '*', 42 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ ';', 59 },
+{ '<', 60 },
+{ '=', 61 },
+{ '>', 62 },
+{ '?', 63 },
+{ '@', 64 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ '[', 91 },
+{ '\\', 92 },
+{ ']', 93 },
+{ '^', 94 },
+{ '_', 95 },
+{ '`', 96 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+{ '{', 123 },
+{ '|', 124 },
+{ '}', 125 },
+{ '~', 126 }
+};
+
+int der_ia5_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].code == c) {
+ return ia5_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_ia5_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].value == v) {
+ return ia5_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of IA5 STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_ia5_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (noctets < 128) {
+ /* 16 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 16 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 16 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 16 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c b/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c
new file mode 100644
index 0000000..e68b2c9
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c
@@ -0,0 +1,110 @@
+/* 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_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a mp_int integer
+ @param in The DER encoded data
+ @param inlen Size of DER encoded data
+ @param num The first mp_int to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_integer(const unsigned char *in, unsigned long inlen, mp_int *num)
+{
+ unsigned long x, y, z;
+ int err;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* min DER INTEGER is 0x02 01 00 == 0 */
+ if (inlen < (1 + 1 + 1)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* ok expect 0x02 when we AND with 0001 1111 [1F] */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* now decode the len stuff */
+ z = in[x++];
+
+ if ((z & 0x80) == 0x00) {
+ /* short form */
+
+ /* will it overflow? */
+ if (x + z > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* no so read it */
+ if ((err = mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in + x, z))) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* long form */
+ z &= 0x7F;
+
+ /* will number of length bytes overflow? (or > 4) */
+ if (((x + z) > inlen) || (z > 4) || (z == 0)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* now read it in */
+ y = 0;
+ while (z--) {
+ y = ((unsigned long)(in[x++])) | (y << 8);
+ }
+
+ /* now will reading y bytes overrun? */
+ if ((x + y) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* no so read it */
+ if ((err = mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in + x, y))) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* see if it's negative */
+ if (in[x] & 0x80) {
+ mp_int tmp;
+ if (mp_init(&tmp) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+
+ if (mp_2expt(&tmp, mp_count_bits(num)) != MP_OKAY || mp_sub(num, &tmp, num) != MP_OKAY) {
+ mp_clear(&tmp);
+ return CRYPT_MEM;
+ }
+ mp_clear(&tmp);
+ }
+
+ return CRYPT_OK;
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/06/01 00:06:05 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c b/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c
new file mode 100644
index 0000000..f0f41be
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c
@@ -0,0 +1,128 @@
+/* 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_integer.c
+ ASN.1 DER, encode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */
+/**
+ Store a mp_int integer
+ @param num The first mp_int to encode
+ @param out [out] The destination for the DER encoded integers
+ @param outlen [in/out] The max size and resulting size of the DER encoded integers
+ @return CRYPT_OK if successful
+*/
+int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long tmplen, y;
+ int err, leading_zero;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* find out how big this will be */
+ if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < tmplen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (mp_cmp_d(num, 0) != MP_LT) {
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
+ y = mp_unsigned_bin_size(num) + leading_zero;
+ } else {
+ leading_zero = 0;
+ y = mp_count_bits(num);
+ y = y + (8 - (y & 7));
+ y = y >> 3;
+
+ }
+
+ /* now store initial data */
+ *out++ = 0x02;
+ if (y < 128) {
+ /* short form */
+ *out++ = (unsigned char)y;
+ } else if (y < 256) {
+ *out++ = 0x81;
+ *out++ = y;
+ } else if (y < 65536UL) {
+ *out++ = 0x82;
+ *out++ = (y>>8)&255;
+ *out++ = y;
+ } else if (y < 16777216UL) {
+ *out++ = 0x83;
+ *out++ = (y>>16)&255;
+ *out++ = (y>>8)&255;
+ *out++ = y;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* now store msbyte of zero if num is non-zero */
+ if (leading_zero) {
+ *out++ = 0x00;
+ }
+
+ /* if it's not zero store it as big endian */
+ if (mp_cmp_d(num, 0) == MP_GT) {
+ /* now store the mpint */
+ if ((err = mp_to_unsigned_bin(num, out)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+ } else if (mp_iszero(num) != MP_YES) {
+ mp_int tmp;
+ /* negative */
+ if (mp_init(&tmp) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+
+ /* 2^roundup and subtract */
+ y = mp_count_bits(num);
+ y = y + (8 - (y & 7));
+ if (mp_2expt(&tmp, y) != MP_OKAY || mp_add(&tmp, num, &tmp) != MP_OKAY) {
+ mp_clear(&tmp);
+ return CRYPT_MEM;
+ }
+
+ if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return mpi_to_ltc_error(err);
+ }
+ mp_clear(&tmp);
+ }
+
+ /* we good */
+ *outlen = tmplen;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c b/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c
new file mode 100644
index 0000000..1bfee45
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c
@@ -0,0 +1,81 @@
+/* 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_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The mp_int to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_integer(mp_int *num, unsigned long *outlen)
+{
+ unsigned long z, len;
+ int leading_zero;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (mp_cmp_d(num, 0) != MP_LT) {
+ /* positive */
+
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* size for bignum */
+ z = len = leading_zero + mp_unsigned_bin_size(num);
+ } else {
+ /* it's negative */
+ /* find power of 2 that is a multiple of eight and greater than count bits */
+ leading_zero = 0;
+ z = mp_count_bits(num);
+ z = z + (8 - (z & 7));
+ len = z = z >> 3;
+ }
+
+ /* now we need a length */
+ if (z < 128) {
+ /* short form */
+ ++len;
+ } else {
+ /* long form (relies on z != 0), assumes length bytes < 128 */
+ ++len;
+
+ while (z) {
+ ++len;
+ z >>= 8;
+ }
+ }
+
+ /* we need a 0x02 to indicate it's INTEGER */
+ ++len;
+
+ /* return length */
+ *outlen = len;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c
new file mode 100644
index 0000000..c69c9a3
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c
@@ -0,0 +1,99 @@
+/* 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_object_identifier.c
+ ASN.1 DER, Decode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Decode OID data and store the array of integers in words
+ @param in The OID DER encoded data
+ @param inlen The length of the OID data
+ @param words [out] The destination of the OID words
+ @param outlen [in/out] The number of OID words
+ @return CRYPT_OK if successful
+*/
+int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
+ unsigned long *words, unsigned long *outlen)
+{
+ unsigned long x, y, t, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* header is at least 3 bytes */
+ if (inlen < 3) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* must be room for at least two words */
+ if (*outlen < 2) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode the packet header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x06) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the length */
+ if (in[x] < 128) {
+ len = in[x++];
+ } else {
+ if (in[x] < 0x81 || in[x] > 0x82) {
+ return CRYPT_INVALID_PACKET;
+ }
+ y = in[x++] & 0x7F;
+ len = 0;
+ while (y--) {
+ len = (len << 8) | (unsigned long)in[x++];
+ }
+ }
+
+ if (len < 1 || (len + x) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode word1 and word2 */
+ --len;
+ t = in[x++];
+ words[0] = t/40;
+ words[1] = t%40;
+
+ /* decode rest */
+ y = 2;
+ t = 0;
+ while (len--) {
+ t = (t << 7) | (in[x] & 0x7F);
+ if (!(in[x++] & 0x80)) {
+ /* store t */
+ if (y >= *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ words[y++] = t;
+ t = 0;
+ }
+ }
+
+ *outlen = y;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c
new file mode 100644
index 0000000..16eb112
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c
@@ -0,0 +1,103 @@
+/* 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_object_identifier.c
+ ASN.1 DER, Encode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Encode an OID
+ @param words The words to encode (upto 32-bits each)
+ @param nwords The number of words in the OID
+ @param out [out] Destination of OID data
+ @param outlen [in/out] The max and resulting size of the OID
+ @return CRYPT_OK if successful
+*/
+int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long i, x, y, z, t, mask;
+ int err;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* check length */
+ if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) {
+ return err;
+ }
+ if (x > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* compute length to store OID data */
+ z = 1;
+ for (y = 2; y < nwords; y++) {
+ t = der_object_identifier_bits(words[y]);
+ z += t/7 + ((t%7) ? 1 : 0);
+ }
+
+ /* store header + length */
+ x = 0;
+ out[x++] = 0x06;
+ if (z < 128) {
+ out[x++] = z;
+ } else if (z < 256) {
+ out[x++] = 0x81;
+ out[x++] = z;
+ } else if (z < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (z>>8)&255;
+ out[x++] = z&255;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store first byte */
+ out[x++] = words[0] * 40 + words[1];
+
+ for (i = 2; i < nwords; i++) {
+ /* store 7 bit words in little endian */
+ t = words[i] & 0xFFFFFFFF;
+ if (t) {
+ y = x;
+ mask = 0;
+ while (t) {
+ out[x++] = (t & 0x7F) | mask;
+ t >>= 7;
+ mask |= 0x80; /* upper bit is set on all but the last byte */
+ }
+ /* now swap bytes y...x-1 */
+ z = x - 1;
+ while (y < z) {
+ t = out[y]; out[y] = out[z]; out[z] = t;
+ ++y;
+ --z;
+ }
+ } else {
+ /* zero word */
+ out[x++] = 0x00;
+ }
+ }
+
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c b/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c
new file mode 100644
index 0000000..d03d1a7
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c
@@ -0,0 +1,84 @@
+/* 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_object_identifier.c
+ ASN.1 DER, get length of Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+unsigned long der_object_identifier_bits(unsigned long x)
+{
+ unsigned long c;
+ x &= 0xFFFFFFFF;
+ c = 0;
+ while (x) {
+ ++c;
+ x >>= 1;
+ }
+ return c;
+}
+
+
+/**
+ Gets length of DER encoding of Object Identifier
+ @param nwords The number of OID words
+ @param words The actual OID words to get the size of
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen)
+{
+ unsigned long y, z, t;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+
+ /* must be >= 2 words */
+ if (nwords < 2) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* word1 = 0,1,2 and word2 0..39 */
+ if (words[0] > 2 || words[1] > 39) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* leading byte of first two words */
+ z = 1;
+ for (y = 2; y < nwords; y++) {
+ t = der_object_identifier_bits(words[y]);
+ z += t/7 + ((t%7) ? 1 : 0);
+ }
+
+ /* now depending on the length our length encoding changes */
+ if (z < 128) {
+ z += 2;
+ } else if (z < 256) {
+ z += 3;
+ } else if (z < 65536UL) {
+ z += 4;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *outlen = z;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c b/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c
new file mode 100644
index 0000000..2d3800f
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c
@@ -0,0 +1,90 @@
+/* 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_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a OCTET STRING
+ @param in The DER encoded OCTET STRING
+ @param inlen The size of the DER OCTET STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x04 */
+ if ((in[0] & 0x1F) != 0x04) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ out[y] = in[x++];
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c b/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c
new file mode 100644
index 0000000..f34b708
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c
@@ -0,0 +1,85 @@
+/* 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_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store an OCTET STRING
+ @param in The array of OCTETS to store (one per char)
+ @param inlen The number of OCTETS to store
+ @param out [out] The destination for the DER encoded OCTET STRING
+ @param outlen [in/out] The max size and resulting size of the DER OCTET STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x04;
+ if (inlen < 128) {
+ out[x++] = inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (inlen>>8)&255;
+ out[x++] = inlen&255;
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (inlen>>16)&255;
+ out[x++] = (inlen>>8)&255;
+ out[x++] = inlen&255;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = in[y];
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c b/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c
new file mode 100644
index 0000000..9a0bed3
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c
@@ -0,0 +1,53 @@
+/* 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_octet_string.c
+ ASN.1 DER, get length of OCTET STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of OCTET STRING
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_octet_string(unsigned long noctets, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+
+ if (noctets < 128) {
+ /* 04 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 04 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 04 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 04 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/16 15:08:11 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c b/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c
new file mode 100644
index 0000000..cbc9239
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c
@@ -0,0 +1,95 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a printable STRING
+ @param in The DER encoded printable STRING
+ @param inlen The size of the DER printable STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x13 */
+ if ((in[0] & 0x1F) != 0x13) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_printable_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/21 02:29:54 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c b/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c
new file mode 100644
index 0000000..ab4e8bf
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c
@@ -0,0 +1,84 @@
+/* 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_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store an printable STRING
+ @param in The array of printable to store (one per char)
+ @param inlen The number of printable to store
+ @param out [out] The destination for the DER encoded printable STRING
+ @param outlen [in/out] The max size and resulting size of the DER printable STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x13;
+ if (inlen < 128) {
+ out[x++] = inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (inlen>>8)&255;
+ out[x++] = inlen&255;
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (inlen>>16)&255;
+ out[x++] = (inlen>>8)&255;
+ out[x++] = inlen&255;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = der_printable_char_encode(in[y]);
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/21 02:29:54 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c b/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c
new file mode 100644
index 0000000..34065f2
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c
@@ -0,0 +1,166 @@
+/* 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_printable_string.c
+ ASN.1 DER, get length of Printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} printable_table[] = {
+{ ' ', 32 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ '=', 61 },
+{ '?', 63 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+};
+
+int der_printable_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].code == c) {
+ return printable_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_printable_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].value == v) {
+ return printable_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of Printable STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_printable_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (noctets < 128) {
+ /* 16 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 16 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 16 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 16 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c,v $ */
+/* $Revision: 1.1 $ */
+/* $Date: 2005/05/21 02:29:54 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence.c b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence.c
new file mode 100644
index 0000000..335a882
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence.c
@@ -0,0 +1,234 @@
+/* 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"
+#include <stdarg.h>
+
+
+/**
+ @file der_decode_sequence.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @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_sequence(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *list, unsigned long outlen)
+{
+ int err, type;
+ unsigned long size, x, y, z, i, blksize;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(list != NULL);
+
+ /* get blk size */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* sequence type? */
+ x = 0;
+ if (in[x++] != 0x30) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ if (in[x] < 128) {
+ blksize = in[x++];
+ } else if (in[x] & 0x80) {
+ if (in[x] < 0x81 || in[x] > 0x83) {
+ return CRYPT_INVALID_PACKET;
+ }
+ y = in[x++] & 0x7F;
+
+ /* would reading the len bytes overrun? */
+ if (x + y > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read len */
+ blksize = 0;
+ while (y--) {
+ blksize = (blksize << 8) | (unsigned long)in[x++];
+ }
+ }
+
+ /* would this blksize overflow? */
+ if (x + blksize > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* ok read data */
+ inlen = blksize;
+ for (i = 0; i < outlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_INTEGER:
+ z = inlen;
+ if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ break;
+
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = inlen;
+ if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = der_length_short_integer(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = inlen;
+ if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ break;
+
+ case LTC_ASN1_NULL:
+ if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ x += 2;
+ inlen -= 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = inlen;
+ if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = inlen;
+ if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ break;
+
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = inlen;
+ if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ 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) {
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ 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;
+ }
+ }
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2005/06/18 19:20:23 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c
new file mode 100644
index 0000000..a4a1038
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c
@@ -0,0 +1,124 @@
+/* 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"
+#include <stdarg.h>
+
+
+/**
+ @file der_decode_sequence_multi.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+{
+ int err, type;
+ unsigned long size, x;
+ void *data;
+ va_list args;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(in != NULL);
+
+ /* get size of output that will be required */
+ va_start(args, inlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ 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;
+
+ default:
+ va_end(args);
+ return CRYPT_INVALID_ARG;
+ }
+ }
+ va_end(args);
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(sizeof(*list), x);
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ va_start(args, inlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ 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;
+ break;
+
+ default:
+ va_end(args);
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ va_end(args);
+
+ err = der_decode_sequence(in, inlen, list, x);
+LBL_ERR:
+ XFREE(list);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2005/06/18 19:20:23 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence.c b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence.c
new file mode 100644
index 0000000..d53153c
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence.c
@@ -0,0 +1,281 @@
+/* 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"
+#include <stdarg.h>
+
+
+/**
+ @file der_encode_sequence.c
+ ASN.1 DER, encode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a SEQUENCE
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_sequence(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err, type;
+ unsigned long size, x, y, z, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long*)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* calc header size */
+ z = y;
+ if (y < 128) {
+ y += 2;
+ } else if (y < 256) {
+ /* 0x30 0x81 LL */
+ y += 3;
+ } else if (y < 65536UL) {
+ /* 0x30 0x82 LL LL */
+ y += 4;
+ } else if (y < 16777216UL) {
+ /* 0x30 0x83 LL LL LL */
+ y += 5;
+ } else {
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+ /* too big ? */
+ if (*outlen < y) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* store header */
+ x = 0;
+ out[x++] = 0x30;
+ if (z < 128) {
+ out[x++] = z;
+ } else if (z < 256) {
+ out[x++] = 0x81;
+ out[x++] = z;
+ } else if (z < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (z>>8UL)&255;
+ out[x++] = z&255;
+ } else if (z < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (z>>16UL)&255;
+ out[x++] = (z>>8UL)&255;
+ out[x++] = z&255;
+ }
+
+ /* store data */
+ *outlen -= x;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = *outlen;
+ if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_NULL:
+ out[x++] = 0x05;
+ out[x++] = 0x00;
+ *outlen -= 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = *outlen;
+ if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = *outlen;
+ if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = *outlen;
+ if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *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) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ *outlen = x;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c
new file mode 100644
index 0000000..9ff48b9
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c
@@ -0,0 +1,123 @@
+/* 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"
+#include <stdarg.h>
+
+
+/**
+ @file der_encode_sequence_multi.c
+ ASN.1 DER, encode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
+{
+ int err, type;
+ unsigned long size, x;
+ void *data;
+ va_list args;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ va_start(args, outlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ 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;
+
+ default:
+ va_end(args);
+ return CRYPT_INVALID_ARG;
+ }
+ }
+ va_end(args);
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(sizeof(*list), x);
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ va_start(args, outlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ 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;
+ list[x++].data = data;
+ break;
+
+ default:
+ va_end(args);
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ va_end(args);
+
+ err = der_encode_sequence(list, x, out, outlen);
+LBL_ERR:
+ XFREE(list);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2005/06/18 19:20:23 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c b/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c
new file mode 100644
index 0000000..9120451
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c
@@ -0,0 +1,144 @@
+/* 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"
+#include <stdarg.h>
+
+
+/**
+ @file der_length_sequence.c
+ ASN.1 DER, length a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER sequence
+ @param list The sequences of items in the SEQUENCE
+ @param inlen The number of items
+ @param outlen [out] The length required in octets to store it
+ @return CRYPT_OK on success
+*/
+int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen)
+{
+ int err, type;
+ unsigned long size, x, y, z, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &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;
+ }
+ y += x;
+ break;
+
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* calc header size */
+ z = y;
+ if (y < 128) {
+ y += 2;
+ } else if (y < 256) {
+ /* 0x30 0x81 LL */
+ y += 3;
+ } else if (y < 65536UL) {
+ /* 0x30 0x82 LL LL */
+ y += 4;
+ } else if (y < 16777216UL) {
+ /* 0x30 0x83 LL LL LL */
+ y += 5;
+ } else {
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+ /* store size */
+ *outlen = y;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
diff --git a/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c b/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c
new file mode 100644
index 0000000..7d3d3b7
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c
@@ -0,0 +1,68 @@
+/* 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_short_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a mp_int integer
+ @param in The DER encoded data
+ @param inlen Size of data
+ @param num [out] The integer to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num)
+{
+ unsigned long len, x, y;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* check length */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the packet len */
+ len = in[x++];
+
+ if (x + len > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read number */
+ y = 0;
+ while (len--) {
+ y = (y<<8) | (unsigned long)in[x++];
+ }
+ *num = y;
+
+ return CRYPT_OK;
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/05/23 01:04:13 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c b/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c
new file mode 100644
index 0000000..eb94d38
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c
@@ -0,0 +1,97 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_short_integer.c
+ ASN.1 DER, encode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/* Exports a positive integer as DER format (upto 32-bits in size) */
+/**
+ Store a mp_int integer
+ @param num The integer to encode
+ @param out [out] The destination for the DER encoded integers
+ @param outlen [in/out] The max size and resulting size of the DER encoded integers
+ @return CRYPT_OK if successful
+*/
+int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y, z;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* find out how big this will be */
+ if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* get len of output */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ }
+
+ /* see if msb is set */
+ z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
+
+ /* adjust the number so the msB is non-zero */
+ for (x = 0; (z <= 4) && (x < (4 - z)); x++) {
+ num <<= 8;
+ }
+
+ /* store header */
+ x = 0;
+ out[x++] = 0x02;
+ out[x++] = z;
+
+ /* if 31st bit is set output a leading zero and decrement count */
+ if (z == 5) {
+ out[x++] = 0;
+ --z;
+ }
+
+ /* store values */
+ for (y = 0; y < z; y++) {
+ out[x++] = (num >> 24) & 0xFF;
+ num <<= 8;
+ }
+
+ /* we good */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/23 01:27:03 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c b/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c
new file mode 100644
index 0000000..7324b4a
--- /dev/null
+++ b/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c
@@ -0,0 +1,69 @@
+/* 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_short_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The integer to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_short_integer(unsigned long num, unsigned long *outlen)
+{
+ unsigned long z, y, len;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* get the number of bytes */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ }
+
+ /* we need a 0x02 to indicate it's INTEGER */
+ len = 1;
+
+ /* length byte */
+ ++len;
+
+ /* bytes in value */
+ len += z;
+
+ /* see if msb is set */
+ len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
+
+ /* return length */
+ *outlen = len;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/23 01:35:38 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c b/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c
new file mode 100644
index 0000000..43ba033
--- /dev/null
+++ b/libtomcrypt/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: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2005/06/19 12:07:00 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c b/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c
new file mode 100644
index 0000000..dad8c84
--- /dev/null
+++ b/libtomcrypt/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: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2005/06/19 12:07:00 $ */
diff --git a/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c b/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c
new file mode 100644
index 0000000..84e654a
--- /dev/null
+++ b/libtomcrypt/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: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/06/19 11:23:04 $ */
diff --git a/libtomcrypt/src/pk/dh/dh.c b/libtomcrypt/src/pk/dh/dh.c
new file mode 100644
index 0000000..a54f29b
--- /dev/null
+++ b/libtomcrypt/src/pk/dh/dh.c
@@ -0,0 +1,524 @@
+/* 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 dh.c
+ DH crypto, Tom St Denis
+*/
+
+#ifdef MDH
+
+/* max export size we'll encounter (smaller than this but lets round up a bit) */
+#define DH_BUF_SIZE 1200
+
+/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
+static const struct {
+ int size;
+ char *name, *base, *prime;
+} sets[] = {
+#ifdef DH768
+{
+ 96,
+ "DH-768",
+ "4",
+ "F///////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "//////m3wvV"
+},
+#endif
+#ifdef DH1024
+{
+ 128,
+ "DH-1024",
+ "4",
+ "F///////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////m3C47"
+},
+#endif
+#ifdef DH1280
+{
+ 160,
+ "DH-1280",
+ "4",
+ "F///////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "//////////////////////////////m4kSN"
+},
+#endif
+#ifdef DH1536
+{
+ 192,
+ "DH-1536",
+ "4",
+ "F///////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////m5uqd"
+},
+#endif
+#ifdef DH1792
+{
+ 224,
+ "DH-1792",
+ "4",
+ "F///////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "//////////////////////////////////////////////////////mT/sd"
+},
+#endif
+#ifdef DH2048
+{
+ 256,
+ "DH-2048",
+ "4",
+ "3///////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "/////////////////////////////////////////m8MPh"
+},
+#endif
+#ifdef DH2560
+{
+ 320,
+ "DH-2560",
+ "4",
+ "3///////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "/////mKFpF"
+},
+#endif
+#ifdef DH3072
+{
+ 384,
+ "DH-3072",
+ "4",
+ "3///////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "/////////////////////////////m32nN"
+},
+#endif
+#ifdef DH4096
+{
+ 512,
+ "DH-4096",
+ "4",
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////"
+ "/////////////////////m8pOF"
+},
+#endif
+{
+ 0,
+ NULL,
+ NULL,
+ NULL
+}
+};
+
+static int is_valid_idx(int n)
+{
+ int x;
+
+ for (x = 0; sets[x].size; x++);
+ if ((n < 0) || (n >= x)) {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ Test the DH sub-system (can take a while)
+ @return CRYPT_OK if successful
+*/
+int dh_test(void)
+{
+ mp_int p, g, tmp;
+ int x, err, primality;
+
+ if ((err = mp_init_multi(&p, &g, &tmp, NULL)) != MP_OKAY) { goto error; }
+
+ for (x = 0; sets[x].size != 0; x++) {
+#if 0
+ printf("dh_test():testing size %d-bits\n", sets[x].size * 8);
+#endif
+ if ((err = mp_read_radix(&g,(char *)sets[x].base, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_radix(&p,(char *)sets[x].prime, 64)) != MP_OKAY) { goto error; }
+
+ /* ensure p is prime */
+ if ((err = is_prime(&p, &primality)) != CRYPT_OK) { goto done; }
+ if (primality == 0) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+
+ if ((err = mp_sub_d(&p, 1, &tmp)) != MP_OKAY) { goto error; }
+ if ((err = mp_div_2(&tmp, &tmp)) != MP_OKAY) { goto error; }
+
+ /* ensure (p-1)/2 is prime */
+ if ((err = is_prime(&tmp, &primality)) != CRYPT_OK) { goto done; }
+ if (primality == 0) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+
+ /* now see if g^((p-1)/2) mod p is in fact 1 */
+ if ((err = mp_exptmod(&g, &tmp, &p, &tmp)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&tmp, 1)) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+ }
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ mp_clear_multi(&tmp, &g, &p, NULL);
+ return err;
+}
+
+/**
+ Get the min and max DH key sizes (octets)
+ @param low [out] The smallest key size supported
+ @param high [out] The largest key size supported
+*/
+void dh_sizes(int *low, int *high)
+{
+ int x;
+ LTC_ARGCHK(low != NULL);
+ LTC_ARGCHK(high != NULL);
+ *low = INT_MAX;
+ *high = 0;
+ for (x = 0; sets[x].size != 0; x++) {
+ if (*low > sets[x].size) *low = sets[x].size;
+ if (*high < sets[x].size) *high = sets[x].size;
+ }
+}
+
+/**
+ Returns the key size of a given DH key (octets)
+ @param key The DH key to get the size of
+ @return The size if valid or INT_MAX if not
+*/
+int dh_get_size(dh_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ if (is_valid_idx(key->idx) == 1) {
+ return sets[key->idx].size;
+ } else {
+ return INT_MAX; /* large value that would cause dh_make_key() to fail */
+ }
+}
+
+/**
+ Make a DH key [private key pair]
+ @param prng An active PRNG state
+ @param wprng The index for the PRNG you desire to use
+ @param keysize The key size (octets) desired
+ @param key [out] Where the newly created DH key will be stored
+ @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically.
+*/
+int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key)
+{
+ unsigned char *buf;
+ unsigned long x;
+ mp_int p, g;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+
+ /* good prng? */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* find key size */
+ for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
+#ifdef FAST_PK
+ keysize = MIN(sets[x].size, 32);
+#else
+ keysize = sets[x].size;
+#endif
+
+ if (sets[x].size == 0) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ key->idx = x;
+
+ /* allocate buffer */
+ buf = XMALLOC(keysize);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* make up random string */
+ if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) {
+ err = CRYPT_ERROR_READPRNG;
+ goto error2;
+ }
+
+ /* init parameters */
+ if ((err = mp_init_multi(&g, &p, &key->x, &key->y, NULL)) != MP_OKAY) {
+ goto error;
+ }
+ if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
+
+ /* load the x value */
+ if ((err = mp_read_unsigned_bin(&key->x, buf, keysize)) != MP_OKAY) { goto error; }
+ if ((err = mp_exptmod(&g, &key->x, &p, &key->y)) != MP_OKAY) { goto error; }
+ key->type = PK_PRIVATE;
+
+ if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; }
+
+ /* free up ram */
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+error2:
+ mp_clear_multi(&key->x, &key->y, NULL);
+done:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, keysize);
+#endif
+ mp_clear_multi(&p, &g, NULL);
+ XFREE(buf);
+ return err;
+}
+
+/**
+ Free the allocated ram for a DH key
+ @param key The key which you wish to free
+*/
+void dh_free(dh_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ mp_clear_multi(&key->x, &key->y, NULL);
+}
+
+/**
+ Export a DH key to a binary packet
+ @param out [out] The destination for the key
+ @param outlen [in/out] The max size and resulting size of the DH key
+ @param type Which type of key (PK_PRIVATE or PK_PUBLIC)
+ @param key The key you wish to export
+ @return CRYPT_OK if successful
+*/
+int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
+{
+ unsigned long y, z;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* can we store the static header? */
+ if (*outlen < (PACKET_SIZE + 2)) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* header */
+ y = PACKET_SIZE;
+
+ /* header */
+ out[y++] = type;
+ out[y++] = (unsigned char)(sets[key->idx].size / 8);
+
+ /* export y */
+ OUTPUT_BIGNUM(&key->y, out, y, z);
+
+ if (type == PK_PRIVATE) {
+ /* export x */
+ OUTPUT_BIGNUM(&key->x, out, y, z);
+ }
+
+ /* store header */
+ packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_KEY);
+
+ /* store len */
+ *outlen = y;
+ return CRYPT_OK;
+}
+
+/**
+ Import a DH key from a binary packet
+ @param in The packet to read
+ @param inlen The length of the input packet
+ @param key [out] Where to import the key to
+ @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
+{
+ unsigned long x, y, s;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* make sure valid length */
+ if ((2+PACKET_SIZE) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check type byte */
+ if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* init */
+ if ((err = mp_init_multi(&key->x, &key->y, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ /* advance past packet header */
+ y = PACKET_SIZE;
+
+ /* key type, e.g. private, public */
+ key->type = (int)in[y++];
+
+ /* key size in bytes */
+ s = (unsigned long)in[y++] * 8;
+
+ for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
+ if (sets[x].size == 0) {
+ err = CRYPT_INVALID_KEYSIZE;
+ goto error;
+ }
+ key->idx = (int)x;
+
+ /* type check both values */
+ if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
+ err = CRYPT_PK_TYPE_MISMATCH;
+ goto error;
+ }
+
+ /* is the key idx valid? */
+ if (is_valid_idx(key->idx) != 1) {
+ err = CRYPT_PK_TYPE_MISMATCH;
+ goto error;
+ }
+
+ /* load public value g^x mod p*/
+ INPUT_BIGNUM(&key->y, in, x, y, inlen);
+
+ if (key->type == PK_PRIVATE) {
+ INPUT_BIGNUM(&key->x, in, x, y, inlen);
+ }
+
+ /* eliminate private key if public */
+ if (key->type == PK_PUBLIC) {
+ mp_clear(&key->x);
+ }
+
+ return CRYPT_OK;
+error:
+ mp_clear_multi(&key->y, &key->x, NULL);
+ return err;
+}
+
+/**
+ Create a DH shared secret.
+ @param private_key The private DH key in the pair
+ @param public_key The public DH key in the pair
+ @param out [out] The destination of the shared data
+ @param outlen [in/out] The max size and resulting size of the shared data.
+ @return CRYPT_OK if successful
+*/
+int dh_shared_secret(dh_key *private_key, dh_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ mp_int tmp, p;
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(private_key != NULL);
+ LTC_ARGCHK(public_key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* types valid? */
+ if (private_key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* same idx? */
+ if (private_key->idx != public_key->idx) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ /* compute y^x mod p */
+ if ((err = mp_init_multi(&tmp, &p, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ if ((err = mp_read_radix(&p, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_exptmod(&public_key->y, &private_key->x, &p, &tmp)) != MP_OKAY) { goto error; }
+
+ /* enough space for output? */
+ x = (unsigned long)mp_unsigned_bin_size(&tmp);
+ if (*outlen < x) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto done;
+ }
+ if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) { goto error; }
+ *outlen = x;
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ mp_clear_multi(&p, &tmp, NULL);
+ return err;
+}
+
+#include "dh_sys.c"
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dh/dh.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/dh/dh_sys.c b/libtomcrypt/src/pk/dh/dh_sys.c
new file mode 100644
index 0000000..4f10556
--- /dev/null
+++ b/libtomcrypt/src/pk/dh/dh_sys.c
@@ -0,0 +1,499 @@
+/* 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
+ */
+
+/**
+ @file dh_sys.c
+ DH Crypto, Tom St Denis
+*/
+
+/**
+ Encrypt a short symmetric key with a public DH key
+ @param in The symmetric key to encrypt
+ @param inlen The length of the key (octets)
+ @param out [out] The ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param hash The index of the hash desired (must produce a digest of size >= the size of the plaintext)
+ @param key The public key you wish to encrypt with.
+ @return CRYPT_OK if successful
+*/
+int dh_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ dh_key *key)
+{
+ unsigned char *pub_expt, *dh_shared, *skey;
+ dh_key pubkey;
+ unsigned long x, y, z, hashsize, pubkeysize;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* check that wprng/hash are not invalid */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (inlen > hash_descriptor[hash].hashsize) {
+ return CRYPT_INVALID_HASH;
+ }
+
+ /* allocate memory */
+ pub_expt = XMALLOC(DH_BUF_SIZE);
+ dh_shared = XMALLOC(DH_BUF_SIZE);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (pub_expt == NULL || dh_shared == NULL || skey == NULL) {
+ if (pub_expt != NULL) {
+ XFREE(pub_expt);
+ }
+ if (dh_shared != NULL) {
+ XFREE(dh_shared);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* make a random key and export the public copy */
+ if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ pubkeysize = DH_BUF_SIZE;
+ if ((err = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
+ dh_free(&pubkey);
+ goto LBL_ERR;
+ }
+
+ /* now check if the out buffer is big enough */
+ if (*outlen < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + inlen)) {
+ dh_free(&pubkey);
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* make random key */
+ hashsize = hash_descriptor[hash].hashsize;
+
+ x = DH_BUF_SIZE;
+ if ((err = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
+ dh_free(&pubkey);
+ goto LBL_ERR;
+ }
+ dh_free(&pubkey);
+
+ z = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* store header */
+ packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY);
+
+ /* output header */
+ y = PACKET_SIZE;
+
+ /* size of hash name and the name itself */
+ out[y++] = hash_descriptor[hash].ID;
+
+ /* length of DH pubkey and the key itself */
+ STORE32L(pubkeysize, out+y);
+ y += 4;
+ for (x = 0; x < pubkeysize; x++, y++) {
+ out[y] = pub_expt[x];
+ }
+
+ /* Store the encrypted key */
+ STORE32L(inlen, out+y);
+ y += 4;
+
+ for (x = 0; x < inlen; x++, y++) {
+ out[y] = skey[x] ^ in[x];
+ }
+ *outlen = y;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ /* clean up */
+ zeromem(pub_expt, DH_BUF_SIZE);
+ zeromem(dh_shared, DH_BUF_SIZE);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+ XFREE(skey);
+ XFREE(dh_shared);
+ XFREE(pub_expt);
+
+ return err;
+}
+
+/**
+ Decrypt a DH encrypted symmetric key
+ @param in The DH encrypted packet
+ @param inlen The length of the DH encrypted packet
+ @param out The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext
+ @param key The private DH key corresponding to the public key that encrypted the plaintext
+ @return CRYPT_OK if successful
+*/
+int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ dh_key *key)
+{
+ unsigned char *shared_secret, *skey;
+ unsigned long x, y, z, hashsize, keysize;
+ int hash, err;
+ dh_key pubkey;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* right key type? */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* allocate ram */
+ shared_secret = XMALLOC(DH_BUF_SIZE);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (shared_secret == NULL || skey == NULL) {
+ if (shared_secret != NULL) {
+ XFREE(shared_secret);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* check if initial header should fit */
+ if (inlen < PACKET_SIZE+1+4+4) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ } else {
+ inlen -= PACKET_SIZE+1+4+4;
+ }
+
+ /* is header correct? */
+ if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* now lets get the hash name */
+ y = PACKET_SIZE;
+ hash = find_hash_id(in[y++]);
+ if (hash == -1) {
+ err = CRYPT_INVALID_HASH;
+ goto LBL_ERR;
+ }
+
+ /* common values */
+ hashsize = hash_descriptor[hash].hashsize;
+
+ /* get public key */
+ LOAD32L(x, in+y);
+
+ /* now check if the imported key will fit */
+ if (inlen < x) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ } else {
+ inlen -= x;
+ }
+
+ y += 4;
+ if ((err = dh_import(in+y, x, &pubkey)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+
+ /* make shared key */
+ x = DH_BUF_SIZE;
+ if ((err = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
+ dh_free(&pubkey);
+ goto LBL_ERR;
+ }
+ dh_free(&pubkey);
+
+ z = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* load in the encrypted key */
+ LOAD32L(keysize, in+y);
+
+ /* will the out fit as part of the input */
+ if (inlen < keysize) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ } else {
+ inlen -= keysize;
+ }
+
+ if (keysize > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+ y += 4;
+
+ *outlen = keysize;
+
+ for (x = 0; x < keysize; x++, y++) {
+ out[x] = skey[x] ^ in[y];
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(shared_secret, DH_BUF_SIZE);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(skey);
+ XFREE(shared_secret);
+
+ return err;
+}
+
+/* perform an ElGamal Signature of a hash
+ *
+ * The math works as follows. x is the private key, M is the message to sign
+
+ 1. pick a random k
+ 2. compute a = g^k mod p
+ 3. compute b = (M - xa)/k mod p
+ 4. Send (a,b)
+
+ Now to verify with y=g^x mod p, a and b
+
+ 1. compute y^a * a^b = g^(xa) * g^(k*(M-xa)/k)
+ = g^(xa + (M - xa))
+ = g^M [all mod p]
+
+ 2. Compare against g^M mod p [based on input hash].
+ 3. If result of #2 == result of #1 then signature valid
+*/
+
+/**
+ Sign a message digest using a DH private key
+ @param in The data to sign
+ @param inlen The length of the input (octets)
+ @param out [out] The destination of the signature
+ @param outlen [in/out] The max size and resulting size of the output
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key A private DH key
+ @return CRYPT_OK if successful
+*/
+int dh_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, dh_key *key)
+{
+ mp_int a, b, k, m, g, p, p1, tmp;
+ unsigned char *buf;
+ unsigned long x, y;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* check parameters */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* is the IDX valid ? */
+ if (is_valid_idx(key->idx) != 1) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* allocate ram for buf */
+ buf = XMALLOC(520);
+
+ /* make up a random value k,
+ * since the order of the group is prime
+ * we need not check if gcd(k, r) is 1
+ */
+ if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) !=
+ (unsigned long)(sets[key->idx].size)) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+
+ /* init bignums */
+ if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != MP_OKAY) {
+ err = mpi_to_ltc_error(err);
+ goto LBL_ERR;
+ }
+
+ /* load k and m */
+ if ((err = mp_read_unsigned_bin(&m, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_unsigned_bin(&k, buf, sets[key->idx].size)) != MP_OKAY) { goto error; }
+
+ /* load g, p and p1 */
+ if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_sub_d(&p, 1, &p1)) != MP_OKAY) { goto error; }
+ if ((err = mp_div_2(&p1, &p1)) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */
+
+ /* now get a = g^k mod p */
+ if ((err = mp_exptmod(&g, &k, &p, &a)) != MP_OKAY) { goto error; }
+
+ /* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */
+ if ((err = mp_invmod(&k, &p1, &k)) != MP_OKAY) { goto error; } /* k = 1/k mod p1 */
+ if ((err = mp_mulmod(&a, &key->x, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = xa */
+ if ((err = mp_submod(&m, &tmp, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = M - xa */
+ if ((err = mp_mulmod(&k, &tmp, &p1, &b)) != MP_OKAY) { goto error; } /* b = (M - xa)/k */
+
+ /* check for overflow */
+ if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(&a) + mp_unsigned_bin_size(&b)) > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* store header */
+ y = PACKET_SIZE;
+
+ /* now store them both (a,b) */
+ x = (unsigned long)mp_unsigned_bin_size(&a);
+ STORE32L(x, out+y); y += 4;
+ if ((err = mp_to_unsigned_bin(&a, out+y)) != MP_OKAY) { goto error; }
+ y += x;
+
+ x = (unsigned long)mp_unsigned_bin_size(&b);
+ STORE32L(x, out+y); y += 4;
+ if ((err = mp_to_unsigned_bin(&b, out+y)) != MP_OKAY) { goto error; }
+ y += x;
+
+ /* check if size too big */
+ if (*outlen < y) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* store header */
+ packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_SIGNED);
+ *outlen = y;
+
+ err = CRYPT_OK;
+ goto LBL_ERR;
+error:
+ err = mpi_to_ltc_error(err);
+LBL_ERR:
+ mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);
+
+ XFREE(buf);
+
+ return err;
+}
+
+
+/**
+ Verify the signature given
+ @param sig The signature
+ @param siglen The length of the signature (octets)
+ @param hash The hash that was signed
+ @param hashlen The length of the hash (octets)
+ @param stat [out] Result of signature comparison, 1==valid, 0==invalid
+ @param key The public DH key that signed the hash
+ @return CRYPT_OK if succsessful (even if signature is invalid)
+*/
+int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dh_key *key)
+{
+ mp_int a, b, p, g, m, tmp;
+ unsigned long x, y;
+ int err;
+
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* check initial input length */
+ if (siglen < PACKET_SIZE+4+4) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* header ok? */
+ if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get hash out of packet */
+ y = PACKET_SIZE;
+
+ /* init all bignums */
+ if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ /* load a and b */
+ INPUT_BIGNUM(&a, sig, x, y, siglen);
+ INPUT_BIGNUM(&b, sig, x, y, siglen);
+
+ /* load p and g */
+ if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error1; }
+ if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error1; }
+
+ /* load m */
+ if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error1; }
+
+ /* find g^m mod p */
+ if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY) { goto error1; } /* m = g^m mod p */
+
+ /* find y^a * a^b */
+ if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY) { goto error1; } /* tmp = y^a mod p */
+ if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY) { goto error1; } /* a = a^b mod p */
+ if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY) { goto error1; } /* a = y^a * a^b mod p */
+
+ /* y^a * a^b == g^m ??? */
+ if (mp_cmp(&a, &m) == 0) {
+ *stat = 1;
+ }
+
+ /* clean up */
+ err = CRYPT_OK;
+ goto done;
+error1:
+ err = mpi_to_ltc_error(err);
+error:
+done:
+ mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL);
+ return err;
+}
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dh/dh_sys.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/dsa/dsa_export.c b/libtomcrypt/src/pk/dsa/dsa_export.c
new file mode 100644
index 0000000..5a093d9
--- /dev/null
+++ b/libtomcrypt/src/pk/dsa/dsa_export.c
@@ -0,0 +1,72 @@
+/* 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 dsa_export.c
+ DSA implementation, export key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Export a DSA key to a binary packet
+ @param out [out] Where to store the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of key to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
+{
+ unsigned char flags[1];
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* can we store the static header? */
+ if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ if (type != PK_PUBLIC && type != PK_PRIVATE) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ flags[0] = (type != PK_PUBLIC) ? 1 : 0;
+
+ if (type == PK_PRIVATE) {
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_export.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2005/06/03 19:24:31 $ */
diff --git a/libtomcrypt/src/pk/dsa/dsa_free.c b/libtomcrypt/src/pk/dsa/dsa_free.c
new file mode 100644
index 0000000..9157acb
--- /dev/null
+++ b/libtomcrypt/src/pk/dsa/dsa_free.c
@@ -0,0 +1,34 @@
+/* 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 dsa_free.c
+ DSA implementation, free a DSA key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Free a DSA key
+ @param key The key to free from memory
+*/
+void dsa_free(dsa_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_free.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/dsa/dsa_import.c b/libtomcrypt/src/pk/dsa/dsa_import.c
new file mode 100644
index 0000000..e81bac8
--- /dev/null
+++ b/libtomcrypt/src/pk/dsa/dsa_import.c
@@ -0,0 +1,89 @@
+/* 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 dsa_import.c
+ DSA implementation, import a DSA key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Import a DSA key
+ @param in The binary packet to import from
+ @param inlen The length of the binary packet
+ @param key [out] Where to store the imported key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
+{
+ unsigned char flags[1];
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init key */
+ if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+
+ /* get key type */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if (flags[0] == 1) {
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+ key->type = PK_PRIVATE;
+ } else {
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+ key->type = PK_PUBLIC;
+ }
+ key->qord = mp_unsigned_bin_size(&key->q);
+
+ if (key->qord >= MDSA_MAX_GROUP || key->qord <= 15 ||
+ key->qord >= mp_unsigned_bin_size(&key->p) || (mp_unsigned_bin_size(&key->p) - key->qord) >= MDSA_DELTA) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ return CRYPT_OK;
+error:
+ mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_import.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2005/06/08 23:31:17 $ */
diff --git a/libtomcrypt/src/pk/dsa/dsa_make_key.c b/libtomcrypt/src/pk/dsa/dsa_make_key.c
new file mode 100644
index 0000000..02f69e0
--- /dev/null
+++ b/libtomcrypt/src/pk/dsa/dsa_make_key.c
@@ -0,0 +1,146 @@
+/* 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 dsa_make_key.c
+ DSA implementation, generate a DSA key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Create a DSA key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param group_size Size of the multiplicative group (octets)
+ @param modulus_size Size of the modulus (octets)
+ @param key [out] Where to store the created key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
+{
+ mp_int tmp, tmp2;
+ int err, res;
+ unsigned char *buf;
+
+ LTC_ARGCHK(key != NULL);
+
+ /* check prng */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* check size */
+ if (group_size >= MDSA_MAX_GROUP || group_size <= 15 ||
+ group_size >= modulus_size || (modulus_size - group_size) >= MDSA_DELTA) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* allocate ram */
+ buf = XMALLOC(MDSA_DELTA);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* init mp_ints */
+ if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != MP_OKAY) {
+ err = mpi_to_ltc_error(err);
+ goto LBL_ERR;
+ }
+
+ /* make our prime q */
+ if ((err = rand_prime(&key->q, group_size*8, prng, wprng)) != CRYPT_OK) { goto LBL_ERR; }
+
+ /* double q */
+ if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY) { goto error; }
+
+ /* now make a random string and multply it against q */
+ if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+
+ /* force magnitude */
+ buf[0] |= 0xC0;
+
+ /* force even */
+ buf[modulus_size - group_size - 1] &= ~1;
+
+ if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size)) != MP_OKAY) { goto error; }
+ if ((err = mp_mul(&key->q, &tmp2, &key->p)) != MP_OKAY) { goto error; }
+ if ((err = mp_add_d(&key->p, 1, &key->p)) != MP_OKAY) { goto error; }
+
+ /* now loop until p is prime */
+ for (;;) {
+ if ((err = is_prime(&key->p, &res)) != CRYPT_OK) { goto LBL_ERR; }
+ if (res == MP_YES) break;
+
+ /* add 2q to p and 2 to tmp2 */
+ if ((err = mp_add(&tmp, &key->p, &key->p)) != MP_OKAY) { goto error; }
+ if ((err = mp_add_d(&tmp2, 2, &tmp2)) != MP_OKAY) { goto error; }
+ }
+
+ /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */
+ mp_set(&key->g, 1);
+
+ do {
+ if ((err = mp_add_d(&key->g, 1, &key->g)) != MP_OKAY) { goto error; }
+ if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != MP_OKAY) { goto error; }
+ } while (mp_cmp_d(&tmp, 1) == MP_EQ);
+
+ /* at this point tmp generates a group of order q mod p */
+ mp_exch(&tmp, &key->g);
+
+ /* so now we have our DH structure, generator g, order q, modulus p
+ Now we need a random exponent [mod q] and it's power g^x mod p
+ */
+ do {
+ if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+ if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != MP_OKAY) { goto error; }
+ } while (mp_cmp_d(&key->x, 1) != MP_GT);
+ if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != MP_OKAY) { goto error; }
+
+ key->type = PK_PRIVATE;
+ key->qord = group_size;
+
+ /* shrink the ram required */
+ if ((err = mp_shrink(&key->g)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, MDSA_DELTA);
+#endif
+
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+LBL_ERR:
+ mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+done:
+ mp_clear_multi(&tmp, &tmp2, NULL);
+
+ XFREE(buf);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_make_key.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/06/11 05:45:35 $ */
diff --git a/libtomcrypt/src/pk/dsa/dsa_sign_hash.c b/libtomcrypt/src/pk/dsa/dsa_sign_hash.c
new file mode 100644
index 0000000..48d29a2
--- /dev/null
+++ b/libtomcrypt/src/pk/dsa/dsa_sign_hash.c
@@ -0,0 +1,159 @@
+/* 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 dsa_sign_hash.c
+ DSA implementation, sign a hash, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param r The "r" integer of the signature (caller must initialize with mp_init() first)
+ @param s The "s" integer of the signature (caller must initialize with mp_init() first)
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ mp_int *r, mp_int *s,
+ prng_state *prng, int wprng, dsa_key *key)
+{
+ mp_int k, kinv, tmp;
+ unsigned char *buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* check group order size */
+ if (key->qord >= MDSA_MAX_GROUP) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ buf = XMALLOC(MDSA_MAX_GROUP);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* Init our temps */
+ if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != MP_OKAY) { goto error; }
+
+retry:
+
+ do {
+ /* gen random k */
+ if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+
+ /* read k */
+ if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != MP_OKAY) { goto error; }
+
+ /* k > 1 ? */
+ if (mp_cmp_d(&k, 1) != MP_GT) { goto retry; }
+
+ /* test gcd */
+ if ((err = mp_gcd(&k, &key->q, &tmp)) != MP_OKAY) { goto error; }
+ } while (mp_cmp_d(&tmp, 1) != MP_EQ);
+
+ /* now find 1/k mod q */
+ if ((err = mp_invmod(&k, &key->q, &kinv)) != MP_OKAY) { goto error; }
+
+ /* now find r = g^k mod p mod q */
+ if ((err = mp_exptmod(&key->g, &k, &key->p, r)) != MP_OKAY) { goto error; }
+ if ((err = mp_mod(r, &key->q, r)) != MP_OKAY) { goto error; }
+
+ if (mp_iszero(r) == MP_YES) { goto retry; }
+
+ /* now find s = (in + xr)/k mod q */
+ if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; }
+ if ((err = mp_mul(&key->x, r, s)) != MP_OKAY) { goto error; }
+ if ((err = mp_add(s, &tmp, s)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(s, &kinv, &key->q, s)) != MP_OKAY) { goto error; }
+
+ if (mp_iszero(s) == MP_YES) { goto retry; }
+
+ err = CRYPT_OK;
+ goto LBL_ERR;
+
+error:
+ err = mpi_to_ltc_error(err);
+LBL_ERR:
+ mp_clear_multi(&k, &kinv, &tmp, NULL);
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, MDSA_MAX_GROUP);
+#endif
+ XFREE(buf);
+ return err;
+}
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param out [out] Where to store the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, dsa_key *key)
+{
+ mp_int r, s;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (mp_init_multi(&r, &s, NULL) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = dsa_sign_hash_raw(in, inlen, &r, &s, prng, wprng, key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+LBL_ERR:
+ mp_clear_multi(&r, &s, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_sign_hash.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2005/05/15 21:48:59 $ */
diff --git a/libtomcrypt/src/pk/dsa/dsa_verify_hash.c b/libtomcrypt/src/pk/dsa/dsa_verify_hash.c
new file mode 100644
index 0000000..11e5c33
--- /dev/null
+++ b/libtomcrypt/src/pk/dsa/dsa_verify_hash.c
@@ -0,0 +1,128 @@
+/* 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 dsa_verify_hash.c
+ DSA implementation, verify a signature, Tom St Denis
+*/
+
+
+#ifdef MDSA
+
+/**
+ Verify a DSA signature
+ @param r DSA "r" parameter
+ @param s DSA "s" parameter
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DH key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash_raw( mp_int *r, mp_int *s,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key)
+{
+ mp_int w, v, u1, u2;
+ int err;
+
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* init our variables */
+ if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ /* neither r or s can be null or >q*/
+ if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || mp_cmp(r, &key->q) != MP_LT || mp_cmp(s, &key->q) != MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto done;
+ }
+
+ /* w = 1/s mod q */
+ if ((err = mp_invmod(s, &key->q, &w)) != MP_OKAY) { goto error; }
+
+ /* u1 = m * w mod q */
+ if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != MP_OKAY) { goto error; }
+
+ /* u2 = r*w mod q */
+ if ((err = mp_mulmod(r, &w, &key->q, &u2)) != MP_OKAY) { goto error; }
+
+ /* v = g^u1 * y^u2 mod p mod q */
+ if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != MP_OKAY) { goto error; }
+ if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != MP_OKAY) { goto error; }
+ if ((err = mp_mod(&v, &key->q, &v)) != MP_OKAY) { goto error; }
+
+ /* if r = v then we're set */
+ if (mp_cmp(r, &v) == MP_EQ) {
+ *stat = 1;
+ }
+
+ err = CRYPT_OK;
+ goto done;
+
+error : err = mpi_to_ltc_error(err);
+done : mp_clear_multi(&w, &v, &u1, &u2, NULL);
+ return err;
+}
+
+/**
+ Verify a DSA signature
+ @param sig The signature
+ @param siglen The length of the signature (octets)
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DH key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key)
+{
+ int err;
+ mp_int r, s;
+
+ if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* decode the sequence */
+ if ((err = der_decode_sequence_multi(sig, siglen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* do the op */
+ err = dsa_verify_hash_raw(&r, &s, hash, hashlen, stat, key);
+
+LBL_ERR:
+ mp_clear_multi(&r, &s, NULL);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_hash.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2005/05/15 21:48:59 $ */
diff --git a/libtomcrypt/src/pk/dsa/dsa_verify_key.c b/libtomcrypt/src/pk/dsa/dsa_verify_key.c
new file mode 100644
index 0000000..b7be103
--- /dev/null
+++ b/libtomcrypt/src/pk/dsa/dsa_verify_key.c
@@ -0,0 +1,102 @@
+/* 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 dsa_verify_key.c
+ DSA implementation, verify a key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Verify a DSA key for validity
+ @param key The key to verify
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_verify_key(dsa_key *key, int *stat)
+{
+ mp_int tmp, tmp2;
+ int res, err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to an invalid key */
+ *stat = 0;
+
+ /* first make sure key->q and key->p are prime */
+ if ((err = is_prime(&key->q, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == 0) {
+ return CRYPT_OK;
+ }
+
+
+ if ((err = is_prime(&key->p, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == 0) {
+ return CRYPT_OK;
+ }
+
+ /* now make sure that g is not -1, 0 or 1 and <p */
+ if (mp_cmp_d(&key->g, 0) == MP_EQ || mp_cmp_d(&key->g, 1) == MP_EQ) {
+ return CRYPT_OK;
+ }
+ if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != MP_OKAY) { goto error; }
+ if ((err = mp_sub_d(&key->p, 1, &tmp)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&tmp, &key->g) == MP_EQ || mp_cmp(&key->g, &key->p) != MP_LT) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ /* 1 < y < p-1 */
+ if (!(mp_cmp_d(&key->y, 1) == MP_GT && mp_cmp(&key->y, &tmp) == MP_LT)) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
+ if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != MP_OKAY) { goto error; }
+ if (mp_iszero(&tmp2) != MP_YES) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&tmp, 1) != MP_EQ) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */
+ if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&tmp, 1) != MP_EQ) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ /* at this point we are out of tests ;-( */
+ err = CRYPT_OK;
+ *stat = 1;
+ goto done;
+error: err = mpi_to_ltc_error(err);
+done : mp_clear_multi(&tmp, &tmp2, NULL);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_key.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/ecc/ecc.c b/libtomcrypt/src/pk/ecc/ecc.c
new file mode 100644
index 0000000..469d56d
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc.c
@@ -0,0 +1,1036 @@
+/* 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
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/* size of our temp buffers for exported keys */
+#define ECC_BUF_SIZE 256
+
+/* max private key size */
+#define ECC_MAXSIZE 66
+
+/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
+static const struct {
+ int size;
+ char *name, *prime, *B, *order, *Gx, *Gy;
+} sets[] = {
+#ifdef ECC192
+{
+ 24,
+ "ECC-192",
+ /* prime */
+ "/////////////////////l//////////",
+
+ /* B */
+ "P2456UMSWESFf+chSYGmIVwutkp1Hhcn",
+
+ /* order */
+ "////////////////cTxuDXHhoR6qqYWn",
+
+ /* Gx */
+ "68se3h0maFPylo3hGw680FJ/2ls2/n0I",
+
+ /* Gy */
+ "1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH"
+},
+#endif
+#ifdef ECC224
+{
+ 28,
+ "ECC-224",
+
+ /* prime */
+ "3/////////////////////0000000000000001",
+
+ /* B */
+ "2q1Gg530Ipg/L1CbPGHB2trx/OkYSBEKCZLV+q",
+
+ /* order */
+ "3//////////////////nQYuBZmFXFTAKLSN2ez",
+
+ /* Gx */
+ "2t3WozQxI/Vp8JaBbA0y7JLi8H8ZGoWDOHN1qX",
+
+
+ /* Gy */
+ "2zDsE8jVSZ+qmYt+RDGtMWMWT7P4JLWPc507uq",
+},
+#endif
+#ifdef ECC256
+{
+ 32,
+ "ECC-256",
+ /* Prime */
+ "F////y000010000000000000000////////////////",
+
+ /* B */
+ "5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B",
+
+ /* Order */
+ "F////y00000//////////+yvlgjfnUUXFEvoiByOoLH",
+
+ /* Gx */
+ "6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM",
+
+ /* Gy */
+ "4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r"
+},
+#endif
+#ifdef ECC384
+{
+ 48,
+ "ECC-384",
+ /* prime */
+ "//////////////////////////////////////////x/////00000000003/"
+ "////",
+
+ /* B */
+ "ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ"
+ "x2hl",
+
+ /* Order */
+ "////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC"
+ "nIbp",
+
+ /* Gx and Gy */
+ "geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo"
+ "TWgt",
+
+ "DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG"
+ "wWvV"
+},
+#endif
+#ifdef ECC521
+{
+ 65,
+ "ECC-521",
+ /* prime */
+ "V///////////////////////////////////////////////////////////"
+ "///////////////////////////",
+
+ /* B */
+ "56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l"
+ "JknlmSrSz+8FImqyUz57zHhK3y0",
+
+ /* Order */
+ "V//////////////////////////////////////////+b66XuE/BvPhVym1I"
+ "FS9fT0xjScuYPn7hhjljnwHE6G9",
+
+ /* Gx and Gy */
+ "CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19"
+ "wB/gDupIBF1XMf2c/b+VZ72vRrc",
+
+ "HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0"
+ "J+j1s4rF726edB2G8Y+b7QVqMPG",
+},
+#endif
+{
+ 0,
+ NULL, NULL, NULL, NULL, NULL, NULL
+}
+};
+
+static int is_valid_idx(int n)
+{
+ int x;
+
+ for (x = 0; sets[x].size != 0; x++);
+ if ((n < 0) || (n >= x)) {
+ return 0;
+ }
+ return 1;
+}
+
+static ecc_point *new_point(void)
+{
+ ecc_point *p;
+ p = XMALLOC(sizeof(ecc_point));
+ if (p == NULL) {
+ return NULL;
+ }
+ if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != MP_OKAY) {
+ XFREE(p);
+ return NULL;
+ }
+ return p;
+}
+
+static void del_point(ecc_point *p)
+{
+ /* prevents free'ing null arguments */
+ if (p != NULL) {
+ mp_clear_multi(&p->x, &p->y, &p->z, NULL);
+ XFREE(p);
+ }
+}
+
+static int ecc_map(ecc_point *P, mp_int *modulus, mp_digit mp)
+{
+ mp_int t1, t2;
+ int err;
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* first map z back to normal */
+ if ((err = mp_montgomery_reduce(&P->z, modulus, mp)) != MP_OKAY) { goto error; }
+
+ /* get 1/z */
+ if ((err = mp_invmod(&P->z, modulus, &t1)) != MP_OKAY) { goto error; }
+
+ /* get 1/z^2 and 1/z^3 */
+ if ((err = mp_sqr(&t1, &t2)) != MP_OKAY) { goto error; }
+ if ((err = mp_mod(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
+ if ((err = mp_mul(&t1, &t2, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_mod(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
+
+ /* multiply against x/y */
+ if ((err = mp_mul(&P->x, &t2, &P->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&P->x, modulus, mp)) != MP_OKAY) { goto error; }
+ if ((err = mp_mul(&P->y, &t1, &P->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&P->y, modulus, mp)) != MP_OKAY) { goto error; }
+ mp_set(&P->z, 1);
+
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ mp_clear_multi(&t1, &t2, NULL);
+ return err;
+
+}
+
+/* double a point R = 2P, R can be P*/
+static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_digit mp)
+{
+ mp_int t1, t2;
+ int err;
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ if ((err = mp_copy(&P->x, &R->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&P->y, &R->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&P->z, &R->z)) != MP_OKAY) { goto error; }
+
+ /* t1 = Z * Z */
+ if ((err = mp_sqr(&R->z, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
+ /* Z = Y * Z */
+ if ((err = mp_mul(&R->z, &R->y, &R->z)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&R->z, modulus, mp)) != MP_OKAY) { goto error; }
+ /* Z = 2Z */
+ if ((err = mp_mul_2(&R->z, &R->z)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&R->z, modulus) != MP_LT) {
+ if ((err = mp_sub(&R->z, modulus, &R->z)) != MP_OKAY) { goto error; }
+ }
+
+ /* T2 = X - T1 */
+ if ((err = mp_sub(&R->x, &t1, &t2)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&t2, 0) == MP_LT) {
+ if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
+ }
+ /* T1 = X + T1 */
+ if ((err = mp_add(&t1, &R->x, &t1)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&t1, modulus) != MP_LT) {
+ if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
+ }
+ /* T2 = T1 * T2 */
+ if ((err = mp_mul(&t1, &t2, &t2)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T1 = 2T2 */
+ if ((err = mp_mul_2(&t2, &t1)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&t1, modulus) != MP_LT) {
+ if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
+ }
+ /* T1 = T1 + T2 */
+ if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&t1, modulus) != MP_LT) {
+ if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
+ }
+
+ /* Y = 2Y */
+ if ((err = mp_mul_2(&R->y, &R->y)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&R->y, modulus) != MP_LT) {
+ if ((err = mp_sub(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
+ }
+ /* Y = Y * Y */
+ if ((err = mp_sqr(&R->y, &R->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T2 = Y * Y */
+ if ((err = mp_sqr(&R->y, &t2)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T2 = T2/2 */
+ if (mp_isodd(&t2)) {
+ if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
+ }
+ if ((err = mp_div_2(&t2, &t2)) != MP_OKAY) { goto error; }
+ /* Y = Y * X */
+ if ((err = mp_mul(&R->y, &R->x, &R->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; }
+
+ /* X = T1 * T1 */
+ if ((err = mp_sqr(&t1, &R->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&R->x, modulus, mp)) != MP_OKAY) { goto error; }
+ /* X = X - Y */
+ if ((err = mp_sub(&R->x, &R->y, &R->x)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&R->x, 0) == MP_LT) {
+ if ((err = mp_add(&R->x, modulus, &R->x)) != MP_OKAY) { goto error; }
+ }
+ /* X = X - Y */
+ if ((err = mp_sub(&R->x, &R->y, &R->x)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&R->x, 0) == MP_LT) {
+ if ((err = mp_add(&R->x, modulus, &R->x)) != MP_OKAY) { goto error; }
+ }
+
+ /* Y = Y - X */
+ if ((err = mp_sub(&R->y, &R->x, &R->y)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&R->y, 0) == MP_LT) {
+ if ((err = mp_add(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
+ }
+ /* Y = Y * T1 */
+ if ((err = mp_mul(&R->y, &t1, &R->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; }
+ /* Y = Y - T2 */
+ if ((err = mp_sub(&R->y, &t2, &R->y)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&R->y, 0) == MP_LT) {
+ if ((err = mp_add(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
+ }
+
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ mp_clear_multi(&t1, &t2, NULL);
+ return err;
+}
+
+/* add two different points over Z/pZ, R = P + Q, note R can equal either P or Q */
+static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_digit mp)
+{
+ mp_int t1, t2, x, y, z;
+ int err;
+
+ if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ if ((err = mp_copy(&P->x, &x)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&P->y, &y)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&P->z, &z)) != MP_OKAY) { goto error; }
+
+ /* T1 = Z' * Z' */
+ if ((err = mp_sqr(&Q->z, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
+ /* X = X * T1 */
+ if ((err = mp_mul(&t1, &x, &x)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T1 = Z' * T1 */
+ if ((err = mp_mul(&Q->z, &t1, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
+ /* Y = Y * T1 */
+ if ((err = mp_mul(&t1, &y, &y)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&y, modulus, mp)) != MP_OKAY) { goto error; }
+
+ /* T1 = Z*Z */
+ if ((err = mp_sqr(&z, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T2 = X' * T1 */
+ if ((err = mp_mul(&Q->x, &t1, &t2)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T1 = Z * T1 */
+ if ((err = mp_mul(&z, &t1, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T1 = Y' * T1 */
+ if ((err = mp_mul(&Q->y, &t1, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
+
+ /* Y = Y - T1 */
+ if ((err = mp_sub(&y, &t1, &y)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&y, 0) == MP_LT) {
+ if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
+ }
+ /* T1 = 2T1 */
+ if ((err = mp_mul_2(&t1, &t1)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&t1, modulus) != MP_LT) {
+ if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
+ }
+ /* T1 = Y + T1 */
+ if ((err = mp_add(&t1, &y, &t1)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&t1, modulus) != MP_LT) {
+ if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
+ }
+ /* X = X - T2 */
+ if ((err = mp_sub(&x, &t2, &x)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&x, 0) == MP_LT) {
+ if ((err = mp_add(&x, modulus, &x)) != MP_OKAY) { goto error; }
+ }
+ /* T2 = 2T2 */
+ if ((err = mp_mul_2(&t2, &t2)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&t2, modulus) != MP_LT) {
+ if ((err = mp_sub(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
+ }
+ /* T2 = X + T2 */
+ if ((err = mp_add(&t2, &x, &t2)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&t2, modulus) != MP_LT) {
+ if ((err = mp_sub(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
+ }
+
+ /* if Z' != 1 */
+ if (mp_cmp_d(&Q->z, 1) != MP_EQ) {
+ /* Z = Z * Z' */
+ if ((err = mp_mul(&z, &Q->z, &z)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&z, modulus, mp)) != MP_OKAY) { goto error; }
+ }
+ /* Z = Z * X */
+ if ((err = mp_mul(&z, &x, &z)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&z, modulus, mp)) != MP_OKAY) { goto error; }
+
+ /* T1 = T1 * X */
+ if ((err = mp_mul(&t1, &x, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
+ /* X = X * X */
+ if ((err = mp_sqr(&x, &x)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T2 = T2 * x */
+ if ((err = mp_mul(&t2, &x, &t2)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
+ /* T1 = T1 * X */
+ if ((err = mp_mul(&t1, &x, &t1)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
+
+ /* X = Y*Y */
+ if ((err = mp_sqr(&y, &x)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; }
+ /* X = X - T2 */
+ if ((err = mp_sub(&x, &t2, &x)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&x, 0) == MP_LT) {
+ if ((err = mp_add(&x, modulus, &x)) != MP_OKAY) { goto error; }
+ }
+
+ /* T2 = T2 - X */
+ if ((err = mp_sub(&t2, &x, &t2)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&t2, 0) == MP_LT) {
+ if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
+ }
+ /* T2 = T2 - X */
+ if ((err = mp_sub(&t2, &x, &t2)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&t2, 0) == MP_LT) {
+ if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
+ }
+ /* T2 = T2 * Y */
+ if ((err = mp_mul(&t2, &y, &t2)) != MP_OKAY) { goto error; }
+ if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
+ /* Y = T2 - T1 */
+ if ((err = mp_sub(&t2, &t1, &y)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&y, 0) == MP_LT) {
+ if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
+ }
+ /* Y = Y/2 */
+ if (mp_isodd(&y)) {
+ if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
+ }
+ if ((err = mp_div_2(&y, &y)) != MP_OKAY) { goto error; }
+
+ if ((err = mp_copy(&x, &R->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&y, &R->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&z, &R->z)) != MP_OKAY) { goto error; }
+
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ mp_clear_multi(&t1, &t2, &x, &y, &z, NULL);
+ return err;
+}
+
+/* size of sliding window, don't change this! */
+#define WINSIZE 4
+
+/* perform R = kG where k == integer and G == ecc_point */
+static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus, int map)
+{
+ ecc_point *tG, *M[8];
+ int i, j, err;
+ mp_int mu;
+ mp_digit buf, mp;
+ int first, bitbuf, bitcpy, bitcnt, mode, digidx;
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
+ return CRYPT_INVALID_ARG;
+ }
+ if ((err = mp_init(&mu)) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+ if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
+ mp_clear(&mu);
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* alloc ram for window temps */
+ for (i = 0; i < 8; i++) {
+ M[i] = new_point();
+ if (M[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ del_point(M[j]);
+ }
+ mp_clear(&mu);
+ return CRYPT_MEM;
+ }
+ }
+
+ /* make a copy of G incase R==G */
+ tG = new_point();
+ if (tG == NULL) { err = CRYPT_MEM; goto done; }
+
+ /* tG = G and convert to montgomery */
+ if ((err = mp_mulmod(&G->x, &mu, modulus, &tG->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(&G->y, &mu, modulus, &tG->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(&G->z, &mu, modulus, &tG->z)) != MP_OKAY) { goto error; }
+ mp_clear(&mu);
+
+ /* calc the M tab, which holds kG for k==8..15 */
+ /* M[0] == 8G */
+ if ((err = dbl_point(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = dbl_point(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = dbl_point(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* now find (8+k)G for k=1..7 */
+ for (j = 9; j < 16; j++) {
+ if ((err = add_point(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* setup sliding window */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = k->used - 1;
+ bitcpy = bitbuf = 0;
+ first = 1;
+
+ /* perform ops */
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ if (digidx == -1) {
+ break;
+ }
+ buf = k->dp[digidx--];
+ bitcnt = (int) DIGIT_BIT;
+ }
+
+ /* grab the next msb from the ltiplicand */
+ i = (buf >> (DIGIT_BIT - 1)) & 1;
+ buf <<= 1;
+
+ /* skip leading zero bits */
+ if (mode == 0 && i == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we double */
+ if (mode == 1 && i == 0) {
+ if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (i << (WINSIZE - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == WINSIZE) {
+ /* if this is the first window we do a simple copy */
+ if (first == 1) {
+ /* R = kG [k = first window] */
+ if ((err = mp_copy(&M[bitbuf-8]->x, &R->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&M[bitbuf-8]->y, &R->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&M[bitbuf-8]->z, &R->z)) != MP_OKAY) { goto error; }
+ first = 0;
+ } else {
+ /* normal window */
+ /* ok window is filled so double as required and add */
+ /* double first */
+ for (j = 0; j < WINSIZE; j++) {
+ if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
+ if ((err = add_point(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+ /* empty window and reset */
+ bitcpy = bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then double/add */
+ if (mode == 2 && bitcpy > 0) {
+ /* double then add */
+ for (j = 0; j < bitcpy; j++) {
+ /* only double if we have had at least one add first */
+ if (first == 0) {
+ if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << WINSIZE)) != 0) {
+ if (first == 1){
+ /* first add, so copy */
+ if ((err = mp_copy(&tG->x, &R->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&tG->y, &R->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&tG->z, &R->z)) != MP_OKAY) { goto error; }
+ first = 0;
+ } else {
+ /* then add */
+ if ((err = add_point(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+ }
+ }
+ }
+
+ /* map R back from projective space */
+ if (map) {
+ err = ecc_map(R, modulus, mp);
+ } else {
+ err = CRYPT_OK;
+ }
+
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ del_point(tG);
+ for (i = 0; i < 8; i++) {
+ del_point(M[i]);
+ }
+ return err;
+}
+
+#undef WINSIZE
+
+/**
+ Perform on the ECC system
+ @return CRYPT_OK if successful
+*/
+int ecc_test(void)
+{
+ mp_int modulus, order;
+ ecc_point *G, *GG;
+ int i, err, primality;
+
+ if ((err = mp_init_multi(&modulus, &order, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ G = new_point();
+ GG = new_point();
+ if (G == NULL || GG == NULL) {
+ mp_clear_multi(&modulus, &order, NULL);
+ del_point(G);
+ del_point(GG);
+ return CRYPT_MEM;
+ }
+
+ for (i = 0; sets[i].size; i++) {
+ #if 0
+ printf("Testing %d\n", sets[i].size);
+ #endif
+ if ((err = mp_read_radix(&modulus, (char *)sets[i].prime, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_radix(&order, (char *)sets[i].order, 64)) != MP_OKAY) { goto error; }
+
+ /* is prime actually prime? */
+ if ((err = is_prime(&modulus, &primality)) != CRYPT_OK) { goto done; }
+ if (primality == 0) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+
+ /* is order prime ? */
+ if ((err = is_prime(&order, &primality)) != CRYPT_OK) { goto done; }
+ if (primality == 0) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+
+ if ((err = mp_read_radix(&G->x, (char *)sets[i].Gx, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_radix(&G->y, (char *)sets[i].Gy, 64)) != MP_OKAY) { goto error; }
+ mp_set(&G->z, 1);
+
+ /* then we should have G == (order + 1)G */
+ if ((err = mp_add_d(&order, 1, &order)) != MP_OKAY) { goto error; }
+ if ((err = ecc_mulmod(&order, G, GG, &modulus, 1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(&G->x, &GG->x) != 0 || mp_cmp(&G->y, &GG->y) != 0) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+ }
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ del_point(GG);
+ del_point(G);
+ mp_clear_multi(&order, &modulus, NULL);
+ return err;
+}
+
+void ecc_sizes(int *low, int *high)
+{
+ int i;
+ LTC_ARGCHK(low != NULL);
+ LTC_ARGCHK(high != NULL);
+
+ *low = INT_MAX;
+ *high = 0;
+ for (i = 0; sets[i].size != 0; i++) {
+ if (sets[i].size < *low) {
+ *low = sets[i].size;
+ }
+ if (sets[i].size > *high) {
+ *high = sets[i].size;
+ }
+ }
+}
+
+/**
+ Make a new ECC key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param keysize The keysize for the new key (in octets from 20 to 65 bytes)
+ @param key [out] Destination of the newly created key
+ @return CRYPT_OK if successful, upon error all allocated memory will be freed
+*/
+int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
+{
+ int x, err;
+ ecc_point *base;
+ mp_int prime;
+ unsigned char *buf;
+
+ LTC_ARGCHK(key != NULL);
+
+ /* good prng? */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* find key size */
+ for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
+ keysize = sets[x].size;
+
+ if (keysize > ECC_MAXSIZE || sets[x].size == 0) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ key->idx = x;
+
+ /* allocate ram */
+ base = NULL;
+ buf = XMALLOC(ECC_MAXSIZE);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* make up random string */
+ if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR2;
+ }
+
+ /* setup the key variables */
+ if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, NULL)) != MP_OKAY) {
+ err = mpi_to_ltc_error(err);
+ goto LBL_ERR;
+ }
+ base = new_point();
+ if (base == NULL) {
+ mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, NULL);
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ /* read in the specs for this key */
+ if ((err = mp_read_radix(&prime, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_radix(&base->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_radix(&base->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
+ mp_set(&base->z, 1);
+ if ((err = mp_read_unsigned_bin(&key->k, (unsigned char *)buf, keysize)) != MP_OKAY) { goto error; }
+
+ /* make the public key */
+ if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1)) != CRYPT_OK) { goto LBL_ERR; }
+ key->type = PK_PRIVATE;
+
+ /* shrink key */
+ if ((err = mp_shrink(&key->k)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->pubkey.x)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->pubkey.y)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->pubkey.z)) != MP_OKAY) { goto error; }
+
+ /* free up ram */
+ err = CRYPT_OK;
+ goto LBL_ERR;
+error:
+ err = mpi_to_ltc_error(err);
+LBL_ERR:
+ del_point(base);
+ mp_clear(&prime);
+LBL_ERR2:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, ECC_MAXSIZE);
+#endif
+
+ XFREE(buf);
+
+ return err;
+}
+
+/**
+ Free an ECC key from memory
+ @param key The key you wish to free
+*/
+void ecc_free(ecc_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
+}
+
+/**
+ Export an ECC key as a binary packet
+ @param out [out] Destination for the key
+ @param outlen [in/out] Max size and resulting size of the exported key
+ @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
+{
+ int err;
+ unsigned char flags[1];
+ unsigned long key_size;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* type valid? */
+ if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ if (is_valid_idx(key->idx) == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* we store the NIST byte size */
+ key_size = sets[key->idx].size;
+
+ if (type == PK_PRIVATE) {
+ flags[0] = 1;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, &key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, &key->pubkey.y,
+ LTC_ASN1_INTEGER, 1UL, &key->k,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ flags[0] = 0;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, &key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, &key->pubkey.y,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+
+ return err;
+}
+
+/**
+ Import an ECC key from a binary packet
+ @param in The packet to import
+ @param inlen The length of the packet
+ @param key [out] The destination of the import
+ @return CRYPT_OK if successful, upon error all allocated memory will be freed
+*/
+int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ unsigned long key_size;
+ unsigned char flags[1];
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init key */
+ if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+
+ /* find out what type of key it is */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, &flags,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+
+
+ if (flags[0] == 1) {
+ /* private key */
+ key->type = PK_PRIVATE;
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, &key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, &key->pubkey.y,
+ LTC_ASN1_INTEGER, 1UL, &key->k,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+ } else {
+ /* public key */
+ /* private key */
+ key->type = PK_PUBLIC;
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, &key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, &key->pubkey.y,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+ }
+
+ /* find the idx */
+ for (key->idx = 0; sets[key->idx].size && (unsigned long)sets[key->idx].size != key_size; ++key->idx);
+ if (sets[key->idx].size == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* set z */
+ mp_set(&key->pubkey.z, 1);
+
+ /* we're good */
+ return CRYPT_OK;
+error:
+ mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
+ return err;
+}
+
+/**
+ Create an ECC shared secret between two keys
+ @param private_key The private ECC key
+ @param public_key The public key
+ @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)
+ @param outlen [in/out] The max size and resulting size of the shared secret
+ @return CRYPT_OK if successful
+*/
+int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x;
+ ecc_point *result;
+ mp_int prime;
+ int err;
+
+ LTC_ARGCHK(private_key != NULL);
+ LTC_ARGCHK(public_key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* type valid? */
+ if (private_key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ if (is_valid_idx(private_key->idx) == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (private_key->idx != public_key->idx) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ /* make new point */
+ result = new_point();
+ if (result == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = mp_init(&prime)) != MP_OKAY) {
+ del_point(result);
+ return mpi_to_ltc_error(err);
+ }
+
+ if ((err = mp_read_radix(&prime, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; }
+ if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime, 1)) != CRYPT_OK) { goto done1; }
+
+ x = (unsigned long)mp_unsigned_bin_size(&prime);
+ if (*outlen < x) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto done1;
+ }
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(&result->x, out + (x - mp_unsigned_bin_size(&result->x)))) != MP_OKAY) { goto error; }
+
+ err = CRYPT_OK;
+ *outlen = x;
+ goto done1;
+error:
+ err = mpi_to_ltc_error(err);
+done1:
+ mp_clear(&prime);
+ del_point(result);
+ return err;
+}
+
+/**
+ Get the size of an ECC key
+ @param key The key to get the size of
+ @return The size (octets) of the key or INT_MAX on error
+*/
+int ecc_get_size(ecc_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ if (is_valid_idx(key->idx))
+ return sets[key->idx].size;
+ else
+ return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
+}
+
+#include "ecc_sys.c"
+
+#endif
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc.c,v $ */
+/* $Revision: 1.20 $ */
+/* $Date: 2005/06/14 20:42:28 $ */
diff --git a/libtomcrypt/src/pk/ecc/ecc_sys.c b/libtomcrypt/src/pk/ecc/ecc_sys.c
new file mode 100644
index 0000000..65ead31
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_sys.c
@@ -0,0 +1,462 @@
+/* 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
+ */
+
+/**
+ @file ecc_sys.c
+ ECC Crypto, Tom St Denis
+*/
+
+/**
+ Encrypt a symmetric key with ECC
+ @param in The symmetric key you want to encrypt
+ @param inlen The length of the key to encrypt (octets)
+ @param out [out] The destination for the ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param hash The index of the hash you want to use
+ @param key The ECC key you want to encrypt to
+ @return CRYPT_OK if successful
+*/
+int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ ecc_key *key)
+{
+ unsigned char *pub_expt, *ecc_shared, *skey;
+ ecc_key pubkey;
+ unsigned long x, y, pubkeysize;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* check that wprng/cipher/hash are not invalid */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (inlen > hash_descriptor[hash].hashsize) {
+ return CRYPT_INVALID_HASH;
+ }
+
+ /* make a random key and export the public copy */
+ if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
+ return err;
+ }
+
+ pub_expt = XMALLOC(ECC_BUF_SIZE);
+ ecc_shared = XMALLOC(ECC_BUF_SIZE);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
+ if (pub_expt != NULL) {
+ XFREE(pub_expt);
+ }
+ if (ecc_shared != NULL) {
+ XFREE(ecc_shared);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ ecc_free(&pubkey);
+ return CRYPT_MEM;
+ }
+
+ pubkeysize = ECC_BUF_SIZE;
+ if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+
+ /* make random key */
+ x = ECC_BUF_SIZE;
+ if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+ ecc_free(&pubkey);
+ y = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* Encrypt key */
+ for (x = 0; x < inlen; x++) {
+ skey[x] ^= in[x];
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID,
+ LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt,
+ LTC_ASN1_OCTET_STRING, inlen, skey,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ /* clean up */
+ zeromem(pub_expt, ECC_BUF_SIZE);
+ zeromem(ecc_shared, ECC_BUF_SIZE);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(skey);
+ XFREE(ecc_shared);
+ XFREE(pub_expt);
+
+ return err;
+}
+
+/**
+ Decrypt an ECC encrypted key
+ @param in The ciphertext
+ @param inlen The length of the ciphertext (octets)
+ @param out [out] The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext
+ @param key The corresponding private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ ecc_key *key)
+{
+ unsigned char *ecc_shared, *skey, *pub_expt;
+ unsigned long x, y, hashOID[32];
+ int hash, err;
+ ecc_key pubkey;
+ ltc_asn1_list decode[3];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* right key type? */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* decode to find out hash */
+ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
+
+ if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) {
+ return err;
+ }
+ for (hash = 0; hash_descriptor[hash].name != NULL &&
+ (hash_descriptor[hash].OIDlen != decode[0].size ||
+ memcmp(hash_descriptor[hash].OID, hashOID, sizeof(unsigned long)*decode[0].size)); hash++);
+
+ if (hash_descriptor[hash].name == NULL) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* we now have the hash! */
+
+ /* allocate memory */
+ pub_expt = XMALLOC(ECC_BUF_SIZE);
+ ecc_shared = XMALLOC(ECC_BUF_SIZE);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
+ if (pub_expt != NULL) {
+ XFREE(pub_expt);
+ }
+ if (ecc_shared != NULL) {
+ XFREE(ecc_shared);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ return CRYPT_MEM;
+ }
+ LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE);
+ LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);
+
+ /* read the structure in now */
+ if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* import ECC key from packet */
+ if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* make shared key */
+ x = ECC_BUF_SIZE;
+ if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+ ecc_free(&pubkey);
+
+ y = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* ensure the hash of the shared secret is at least as big as the encrypt itself */
+ if (decode[2].size > y) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* avoid buffer overflow */
+ if (*outlen < decode[2].size) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* Decrypt the key */
+ for (x = 0; x < decode[2].size; x++) {
+ out[x] = skey[x] ^ ecc_shared[x];
+ }
+ *outlen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(pub_expt, ECC_BUF_SIZE);
+ zeromem(ecc_shared, ECC_BUF_SIZE);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(pub_expt);
+ XFREE(ecc_shared);
+ XFREE(skey);
+
+ return err;
+}
+
+/**
+ Sign a message digest
+ @param in The message digest to sign
+ @param inlen The length of the digest
+ @param out [out] The destination for the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param key A private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_key *key)
+{
+ ecc_key pubkey;
+ mp_int r, s, e, p;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* is this a private key? */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* is the IDX valid ? */
+ if (is_valid_idx(key->idx) != 1) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get the hash and load it as a bignum into 'e' */
+ /* init the bignums */
+ if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != MP_OKAY) {
+ ecc_free(&pubkey);
+ err = mpi_to_ltc_error(err);
+ goto LBL_ERR;
+ }
+ if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_unsigned_bin(&e, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; }
+
+ /* make up a key and export the public copy */
+ for (;;) {
+ if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* find r = x1 mod n */
+ if ((err = mp_mod(&pubkey.pubkey.x, &p, &r)) != MP_OKAY) { goto error; }
+
+ if (mp_iszero(&r)) {
+ ecc_free(&pubkey);
+ } else {
+ /* find s = (e + xr)/k */
+ if ((err = mp_invmod(&pubkey.k, &p, &pubkey.k)) != MP_OKAY) { goto error; } /* k = 1/k */
+ if ((err = mp_mulmod(&key->k, &r, &p, &s)) != MP_OKAY) { goto error; } /* s = xr */
+ if ((err = mp_addmod(&e, &s, &p, &s)) != MP_OKAY) { goto error; } /* s = e + xr */
+ if ((err = mp_mulmod(&s, &pubkey.k, &p, &s)) != MP_OKAY) { goto error; } /* s = (e + xr)/k */
+
+ if (mp_iszero(&s)) {
+ ecc_free(&pubkey);
+ } else {
+ break;
+ }
+ }
+ }
+
+ /* store as SEQUENCE { r, s -- integer } */
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL);
+ goto LBL_ERR;
+error:
+ err = mpi_to_ltc_error(err);
+LBL_ERR:
+ mp_clear_multi(&r, &s, &p, &e, NULL);
+ ecc_free(&pubkey);
+
+ return err;
+}
+
+/* verify
+ *
+ * w = s^-1 mod n
+ * u1 = xw
+ * u2 = rw
+ * X = u1*G + u2*Q
+ * v = X_x1 mod n
+ * accept if v == r
+ */
+
+/**
+ Verify an ECC signature
+ @param sig The signature to verify
+ @param siglen The length of the signature (octets)
+ @param hash The hash (message digest) that was signed
+ @param hashlen The length of the hash (octets)
+ @param stat Result of signature, 1==valid, 0==invalid
+ @param key The corresponding public ECC key
+ @return CRYPT_OK if successful (even if the signature is not valid)
+*/
+int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key)
+{
+ ecc_point *mG, *mQ;
+ mp_int r, s, v, w, u1, u2, e, p, m;
+ mp_digit mp;
+ int err;
+
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* is the IDX valid ? */
+ if (is_valid_idx(key->idx) != 1) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* allocate ints */
+ if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+
+ /* allocate points */
+ mG = new_point();
+ mQ = new_point();
+ if (mQ == NULL || mG == NULL) {
+ err = CRYPT_MEM;
+ goto done;
+ }
+
+ /* parse header */
+ if ((err = der_decode_sequence_multi(sig, siglen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto done;
+ }
+
+ /* get the order */
+ if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY) { goto error; }
+
+ /* get the modulus */
+ if ((err = mp_read_radix(&m, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
+
+ /* check for zero */
+ if (mp_iszero(&r) || mp_iszero(&s) || mp_cmp(&r, &p) != MP_LT || mp_cmp(&s, &p) != MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto done;
+ }
+
+ /* read hash */
+ if ((err = mp_read_unsigned_bin(&e, (unsigned char *)hash, (int)hashlen)) != MP_OKAY) { goto error; }
+
+ /* w = s^-1 mod n */
+ if ((err = mp_invmod(&s, &p, &w)) != MP_OKAY) { goto error; }
+
+ /* u1 = ew */
+ if ((err = mp_mulmod(&e, &w, &p, &u1)) != MP_OKAY) { goto error; }
+
+ /* u2 = rw */
+ if ((err = mp_mulmod(&r, &w, &p, &u2)) != MP_OKAY) { goto error; }
+
+ /* find mG = u1*G */
+ if ((err = mp_read_radix(&mG->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
+ if ((err = mp_read_radix(&mG->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
+ mp_set(&mG->z, 1);
+ if ((err = ecc_mulmod(&u1, mG, mG, &m, 0)) != CRYPT_OK) { goto done; }
+
+ /* find mQ = u2*Q */
+ if ((err = mp_copy(&key->pubkey.x, &mQ->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&key->pubkey.y, &mQ->y)) != MP_OKAY) { goto error; }
+ if ((err = mp_copy(&key->pubkey.z, &mQ->z)) != MP_OKAY) { goto error; }
+ if ((err = ecc_mulmod(&u2, mQ, mQ, &m, 0)) != CRYPT_OK) { goto done; }
+
+ /* find the montgomery mp */
+ if ((err = mp_montgomery_setup(&m, &mp)) != MP_OKAY) { goto error; }
+ /* add them */
+ if ((err = add_point(mQ, mG, mG, &m, mp)) != CRYPT_OK) { goto done; }
+
+ /* reduce */
+ if ((err = ecc_map(mG, &m, mp)) != CRYPT_OK) { goto done; }
+
+ /* v = X_x1 mod n */
+ if ((err = mp_mod(&mG->x, &p, &v)) != CRYPT_OK) { goto done; }
+
+ /* does v == r */
+ if (mp_cmp(&v, &r) == MP_EQ) {
+ *stat = 1;
+ }
+
+ /* clear up and return */
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ del_point(mG);
+ del_point(mQ);
+ mp_clear_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL);
+ return err;
+}
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sys.c,v $ */
+/* $Revision: 1.18 $ */
+/* $Date: 2005/06/14 20:47:55 $ */
diff --git a/libtomcrypt/src/pk/packet_store_header.c b/libtomcrypt/src/pk/packet_store_header.c
new file mode 100644
index 0000000..855ca70
--- /dev/null
+++ b/libtomcrypt/src/pk/packet_store_header.c
@@ -0,0 +1,33 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+#ifdef PACKET
+
+void packet_store_header(unsigned char *dst, int section, int subsection)
+{
+ LTC_ARGCHK(dst != NULL);
+
+ /* store version number */
+ dst[0] = (unsigned char)(CRYPT&255);
+ dst[1] = (unsigned char)((CRYPT>>8)&255);
+
+ /* store section and subsection */
+ dst[2] = (unsigned char)(section & 255);
+ dst[3] = (unsigned char)(subsection & 255);
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/packet_store_header.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/packet_valid_header.c b/libtomcrypt/src/pk/packet_valid_header.c
new file mode 100644
index 0000000..59db0f7
--- /dev/null
+++ b/libtomcrypt/src/pk/packet_valid_header.c
@@ -0,0 +1,41 @@
+/* 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"
+
+#ifdef PACKET
+
+int packet_valid_header(unsigned char *src, int section, int subsection)
+{
+ unsigned long ver;
+
+ LTC_ARGCHK(src != NULL);
+
+ /* check version */
+ ver = ((unsigned long)src[0]) | ((unsigned long)src[1] << 8U);
+ if (CRYPT < ver) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check section and subsection */
+ if (section != (int)src[2] || subsection != (int)src[3]) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/packet_valid_header.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c
new file mode 100644
index 0000000..3e68eb8
--- /dev/null
+++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c
@@ -0,0 +1,55 @@
+/* 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 pkcs_1_i2osp.c
+ Integer to Octet I2OSP, Tom St Denis
+*/
+
+#ifdef PKCS_1
+
+/* always stores the same # of bytes, pads with leading zero bytes
+ as required
+ */
+
+/**
+ PKCS #1 Integer to binary
+ @param n The integer to store
+ @param modulus_len The length of the RSA modulus
+ @param out [out] The destination for the integer
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_i2osp(mp_int *n, unsigned long modulus_len, unsigned char *out)
+{
+ int err;
+ unsigned long size;
+
+ size = mp_unsigned_bin_size(n);
+
+ if (size > modulus_len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store it */
+ zeromem(out, modulus_len);
+ if ((err = mp_to_unsigned_bin(n, out+(modulus_len-size))) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+ return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c
new file mode 100644
index 0000000..aac7494
--- /dev/null
+++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c
@@ -0,0 +1,108 @@
+/* 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 pkcs_1_mgf1.c
+ The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis
+*/
+
+#ifdef PKCS_1
+
+/**
+ Perform PKCS #1 MGF1 (internal)
+ @param seed The seed for MGF1
+ @param seedlen The length of the seed
+ @param hash_idx The index of the hash desired
+ @param mask [out] The destination
+ @param masklen The length of the mask desired
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen,
+ int hash_idx,
+ unsigned char *mask, unsigned long masklen)
+{
+ unsigned long hLen, x;
+ ulong32 counter;
+ int err;
+ hash_state *md;
+ unsigned char *buf;
+
+ LTC_ARGCHK(seed != NULL);
+ LTC_ARGCHK(mask != NULL);
+
+ /* ensure valid hash */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get hash output size */
+ hLen = hash_descriptor[hash_idx].hashsize;
+
+ /* allocate memory */
+ md = XMALLOC(sizeof(hash_state));
+ buf = XMALLOC(hLen);
+ if (md == NULL || buf == NULL) {
+ if (md != NULL) {
+ XFREE(md);
+ }
+ if (buf != NULL) {
+ XFREE(buf);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* start counter */
+ counter = 0;
+
+ while (masklen > 0) {
+ /* handle counter */
+ STORE32H(counter, buf);
+ ++counter;
+
+ /* get hash of seed || counter */
+ if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* store it */
+ for (x = 0; x < hLen && masklen > 0; x++, masklen--) {
+ *mask++ = buf[x];
+ }
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, hLen);
+ zeromem(md, sizeof(hash_state));
+#endif
+
+ XFREE(buf);
+ XFREE(md);
+
+ return err;
+}
+
+#endif /* PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
new file mode 100644
index 0000000..cd4931b
--- /dev/null
+++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
@@ -0,0 +1,188 @@
+/* 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 pkcs_1_oaep_decode.c
+ OAEP Padding for PKCS #1, Tom St Denis
+*/
+
+#ifdef PKCS_1
+
+/**
+ PKCS #1 v2.00 OAEP decode
+ @param msg The encoded data to decode
+ @param msglen The length of the encoded data (octets)
+ @param lparam The session or system data (can be NULL)
+ @param lparamlen The length of the lparam
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param hash_idx The index of the hash desired
+ @param out [out] Destination of decoding
+ @param outlen [in/out] The max size and resulting size of the decoding
+ @param res [out] Result of decoding, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if invalid)
+*/
+int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, int hash_idx,
+ unsigned char *out, unsigned long *outlen,
+ int *res)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid packet */
+ *res = 0;
+
+ /* test valid hash */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+ hLen = hash_descriptor[hash_idx].hashsize;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test hash/message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ok so it's now in the form
+
+ 0x00 || maskedseed || maskedDB
+
+ 1 || hLen || modulus_len - hLen - 1
+
+ */
+
+ /* must have leading 0x00 byte */
+ if (msg[0] != 0x00) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* now read the masked seed */
+ x = 1;
+ XMEMCPY(seed, msg + x, hLen);
+ x += hLen;
+
+ /* now read the masked DB */
+ XMEMCPY(DB, msg + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+
+ /* compute lhash and store it in seed [reuse temps!] */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* compare the lhash'es */
+ if (memcmp(seed, DB, hLen) != 0) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* now zeroes before a 0x01 */
+ for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) {
+ /* step... */
+ }
+
+ /* error out if wasn't 0x01 */
+ if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* rest is the message (and skip 0x01) */
+ if ((modulus_len - hLen - 1) - ++x > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* copy message */
+ *outlen = (modulus_len - hLen - 1) - x;
+ XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);
+ x += modulus_len - hLen - 1;
+
+ /* valid packet */
+ *res = 1;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2005/06/18 02:37:06 $ */
diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c
new file mode 100644
index 0000000..12670b5
--- /dev/null
+++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c
@@ -0,0 +1,172 @@
+/* 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 pkcs_1_oaep_encode.c
+ OAEP Padding for PKCS #1, Tom St Denis
+*/
+
+#ifdef PKCS_1
+
+/**
+ PKCS #1 v2.00 OAEP encode
+ @param msg The data to encode
+ @param msglen The length of the data to encode (octets)
+ @param lparam A session or system parameter (can be NULL)
+ @param lparamlen The length of the lparam data
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param prng An active PRNG state
+ @param prng_idx The index of the PRNG desired
+ @param hash_idx The index of the hash desired
+ @param out [out] The destination for the encoded data
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, prng_state *prng,
+ int prng_idx, int hash_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* test valid hash */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* valid prng */
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_descriptor[hash_idx].hashsize;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* get lhash */
+ /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* append PS then 0x01 (to lhash) */
+ x = hLen;
+ y = modulus_len - msglen - 2*hLen - 2;
+ XMEMSET(DB+x, 0, y);
+ x += y;
+
+ /* 0x01 byte */
+ DB[x++] = 0x01;
+
+ /* message (length = msglen) */
+ XMEMCPY(DB+x, msg, msglen);
+ x += msglen;
+
+ /* now choose a random seed */
+ if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* create string of length modulus_len */
+ if (*outlen < modulus_len) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* start output which is 0x00 || maskedSeed || maskedDB */
+ x = 0;
+ out[x++] = 0x00;
+ XMEMCPY(out+x, seed, hLen);
+ x += hLen;
+ XMEMCPY(out+x, DB, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ *outlen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c
new file mode 100644
index 0000000..a9a1858
--- /dev/null
+++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c
@@ -0,0 +1,41 @@
+/* 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 pkcs_1_os2ip.c
+ Octet to Integer OS2IP, Tom St Denis
+*/
+#ifdef PKCS_1
+
+/**
+ Read a binary string into an mp_int
+ @param n [out] The mp_int destination
+ @param in The binary string to read
+ @param inlen The length of the binary string
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_os2ip(mp_int *n, unsigned char *in, unsigned long inlen)
+{
+ int err;
+ /* read it */
+ if ((err = mp_read_unsigned_bin(n, in, inlen)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+ return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c
new file mode 100644
index 0000000..e61c33f
--- /dev/null
+++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c
@@ -0,0 +1,177 @@
+/* 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 pkcs_1_pss_decode.c
+ PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef PKCS_1
+
+/**
+ PKCS #1 v2.00 PSS decode
+ @param msghash The hash to verify
+ @param msghashlen The length of the hash (octets)
+ @param sig The signature data (encoded data)
+ @param siglen The length of the signature data (octets)
+ @param saltlen The length of the salt used (octets)
+ @param hash_idx The index of the hash desired
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param res [out] The result of the comparison, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if the comparison failed)
+*/
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ unsigned long saltlen, int hash_idx,
+ unsigned long modulus_bitlen, int *res)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+ hash_state md;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid */
+ *res = 0;
+
+ /* ensure hash is valid */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_descriptor[hash_idx].hashsize;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) ||
+ (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ensure the 0xBC byte */
+ if (sig[siglen-1] != 0xBC) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* copy out the DB */
+ x = 0;
+ XMEMCPY(DB, sig + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* copy out the hash */
+ XMEMCPY(hash, sig + x, hLen);
+ x += hLen;
+
+ /* check the MSB */
+ if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now clear the first byte [make sure smaller than modulus] */
+ DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
+
+ /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+
+ /* check for zeroes and 0x01 */
+ for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) {
+ if (DB[x] != 0x00) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+ }
+
+ /* check for the 0x01 */
+ if (DB[x++] != 0x01) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
+ if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ zeromem(mask, 8);
+ if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* mask == hash means valid signature */
+ if (memcmp(mask, hash, hLen) == 0) {
+ *res = 1;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c
new file mode 100644
index 0000000..899605c
--- /dev/null
+++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c
@@ -0,0 +1,174 @@
+/* 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 pkcs_1_pss_encode.c
+ PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef PKCS_1
+
+/**
+ PKCS #1 v2.00 Signature Encoding
+ @param msghash The hash to encode
+ @param msghashlen The length of the hash (octets)
+ @param saltlen The length of the salt desired (octets)
+ @param prng An active PRNG context
+ @param prng_idx The index of the PRNG desired
+ @param hash_idx The index of the hash desired
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param out [out] The destination of the encoding
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
+ unsigned long saltlen, prng_state *prng,
+ int prng_idx, int hash_idx,
+ unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+ hash_state md;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* ensure hash and PRNG are valid */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_descriptor[hash_idx].hashsize;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+
+ /* generate random salt */
+ if (saltlen > 0) {
+ if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
+ if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ zeromem(DB, 8);
+ if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+ x = 0;
+ XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2);
+ x += modulus_len - saltlen - hLen - 2;
+ DB[x++] = 0x01;
+ XMEMCPY(DB + x, salt, saltlen);
+ x += saltlen;
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* output is DB || hash || 0xBC */
+ if (*outlen < modulus_len) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* DB len = modulus_len - hLen - 1 */
+ y = 0;
+ XMEMCPY(out + y, DB, modulus_len - hLen - 1);
+ y += modulus_len - hLen - 1;
+
+ /* hash */
+ XMEMCPY(out + y, hash, hLen);
+ y += hLen;
+
+ /* 0xBC */
+ out[y] = 0xBC;
+
+ /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
+ out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
+
+ /* store output size */
+ *outlen = modulus_len;
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c b/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c
new file mode 100644
index 0000000..7cea807
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c
@@ -0,0 +1,93 @@
+/* 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 rsa_decrypt_key.c
+ RSA PKCS #1 OAEP Decryption, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ (PKCS #1 v2.0) decrypt then OAEP depad
+ @param in The ciphertext
+ @param inlen The length of the ciphertext (octets)
+ @param out [out] The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext (octets)
+ @param lparam The system "lparam" value
+ @param lparamlen The length of the lparam value (octets)
+ @param hash_idx The index of the hash desired
+ @param stat [out] Result of the decryption, 1==valid, 0==invalid
+ @param key The corresponding private RSA key
+ @return CRYPT_OK if succcessul (even if invalid)
+*/
+int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ int hash_idx, int *stat,
+ rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmp;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits(&(key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+ if (modulus_bytelen != inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate ram */
+ tmp = XMALLOC(inlen);
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* rsa decode the packet */
+ x = inlen;
+ if ((err = rsa_exptmod(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) {
+ XFREE(tmp);
+ return err;
+ }
+
+ /* now OAEP decode the packet */
+ err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx,
+ out, outlen, stat);
+ XFREE(tmp);
+ return err;
+}
+
+#endif /* MRSA */
+
+
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c b/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c
new file mode 100644
index 0000000..d29aa83
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_encrypt_key.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 rsa_encrypt_key.c
+ RSA PKCS OAEP encryption, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ (PKCS #1 v2.0) OAEP pad then encrypt
+ @param in The plaintext
+ @param inlen The length of the plaintext (octets)
+ @param out [out] The ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param lparam The system "lparam" for the encryption
+ @param lparamlen The length of lparam (octets)
+ @param prng An active PRNG
+ @param prng_idx The index of the desired prng
+ @param hash_idx The index of the desired hash
+ @param key The RSA key to encrypt to
+ @return CRYPT_OK if successful
+*/
+int rsa_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ prng_state *prng, int prng_idx, int hash_idx, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid prng and hash ? */
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits(&(key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+ if (modulus_bytelen > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* OAEP pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_oaep_encode(in, inlen, lparam,
+ lparamlen, modulus_bitlen, prng, prng_idx, hash_idx,
+ out, &x)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* rsa exptmod the OAEP pad */
+ return rsa_exptmod(out, x, out, outlen, PK_PUBLIC, key);
+}
+
+#endif /* MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_export.c b/libtomcrypt/src/pk/rsa/rsa_export.c
new file mode 100644
index 0000000..f2e324d
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_export.c
@@ -0,0 +1,76 @@
+/* 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 rsa_export.c
+ Export RSA PKCS keys, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1]
+ @param out [out] Destination of the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of exported key (PK_PRIVATE or PK_PUBLIC)
+ @param key The RSA key to export
+ @return CRYPT_OK if successful
+*/
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
+{
+ int err;
+ unsigned long zero=0;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* type valid? */
+ if (!(key->type == PK_PRIVATE) && (type == PK_PRIVATE)) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ if (type == PK_PRIVATE) {
+ /* private key */
+ /* output is
+ Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p
+ */
+ if ((err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_INTEGER, 1UL, &key->d,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->dP,
+ LTC_ASN1_INTEGER, 1UL, &key->dQ,
+ LTC_ASN1_INTEGER, 1UL, &key->qP,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* clear zero and return */
+ return CRYPT_OK;
+ } else {
+ /* public key */
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+}
+
+#endif /* MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_export.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2005/06/04 01:42:48 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_exptmod.c b/libtomcrypt/src/pk/rsa/rsa_exptmod.c
new file mode 100644
index 0000000..379404c
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_exptmod.c
@@ -0,0 +1,115 @@
+/* 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 rsa_exptmod.c
+ RSA PKCS exptmod, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ Compute an RSA modular exponentiation
+ @param in The input data to send into RSA
+ @param inlen The length of the input (octets)
+ @param out [out] The destination
+ @param outlen [in/out] The max size and resulting size of the output
+ @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
+ @param key The RSA key to use
+ @return CRYPT_OK if successful
+*/
+int rsa_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ rsa_key *key)
+{
+ mp_int tmp, tmpa, tmpb;
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* is the key of the right type for the operation? */
+ if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* must be a private or public operation */
+ if (which != PK_PRIVATE && which != PK_PUBLIC) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* init and copy into tmp */
+ if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY) { return mpi_to_ltc_error(err); }
+ if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; }
+
+ /* sanity check on the input */
+ if (mp_cmp(&key->N, &tmp) == MP_LT) {
+ err = CRYPT_PK_INVALID_SIZE;
+ goto done;
+ }
+
+ /* are we using the private exponent and is the key optimized? */
+ if (which == PK_PRIVATE) {
+ /* tmpa = tmp^dP mod p */
+ if ((err = mp_exptmod(&tmp, &key->dP, &key->p, &tmpa)) != MP_OKAY) { goto error; }
+
+ /* tmpb = tmp^dQ mod q */
+ if ((err = mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb)) != MP_OKAY) { goto error; }
+
+ /* tmp = (tmpa - tmpb) * qInv (mod p) */
+ if ((err = mp_sub(&tmpa, &tmpb, &tmp)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(&tmp, &key->qP, &key->p, &tmp)) != MP_OKAY) { goto error; }
+
+ /* tmp = tmpb + q * tmp */
+ if ((err = mp_mul(&tmp, &key->q, &tmp)) != MP_OKAY) { goto error; }
+ if ((err = mp_add(&tmp, &tmpb, &tmp)) != MP_OKAY) { goto error; }
+ } else {
+ /* exptmod it */
+ if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != MP_OKAY) { goto error; }
+ }
+
+ /* read it back */
+ x = (unsigned long)mp_unsigned_bin_size(&key->N);
+ if (x > *outlen) {
+ 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 */
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(&tmp, out+(x-mp_unsigned_bin_size(&tmp)))) != MP_OKAY) { goto error; }
+
+ /* clean up and return */
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ mp_clear_multi(&tmp, &tmpa, &tmpb, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_exptmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/06/23 02:10:22 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_free.c b/libtomcrypt/src/pk/rsa/rsa_free.c
new file mode 100644
index 0000000..69eeaec
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_free.c
@@ -0,0 +1,35 @@
+/* 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 rsa_free.c
+ Free an RSA key, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ Free an RSA key from memory
+ @param key The RSA key to free
+*/
+void rsa_free(rsa_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
+ &key->qP, &key->p, &key->q, NULL);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_free.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_import.c b/libtomcrypt/src/pk/rsa/rsa_import.c
new file mode 100644
index 0000000..5706134
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_import.c
@@ -0,0 +1,92 @@
+/* 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 rsa_import.c
+ Import a PKCS RSA key, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1]
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ int err;
+ mp_int zero;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init key */
+ if ((err = mp_init_multi(&zero, &key->e, &key->d, &key->N, &key->dQ,
+ &key->dP, &key->qP, &key->p, &key->q, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if (mp_cmp_d(&key->N, 0) == MP_EQ) {
+ /* it's a private key */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_INTEGER, 1UL, &key->d,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->dP,
+ LTC_ASN1_INTEGER, 1UL, &key->dQ,
+ LTC_ASN1_INTEGER, 1UL, &key->qP,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ key->type = PK_PRIVATE;
+ } else if (mp_cmp_d(&key->N, 1) == MP_EQ) {
+ /* we don't support multi-prime RSA */
+ err = CRYPT_PK_INVALID_TYPE;
+ goto LBL_ERR;
+ } else {
+ /* it's a public key and we lack e */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* free up some ram */
+ mp_clear_multi(&key->p, &key->q, &key->qP, &key->dP, &key->dQ, NULL);
+ key->type = PK_PUBLIC;
+ }
+ return CRYPT_OK;
+LBL_ERR:
+ mp_clear_multi(&zero, &key->d, &key->e, &key->N, &key->dQ, &key->dP,
+ &key->qP, &key->p, &key->q, NULL);
+ return err;
+}
+
+#endif /* MRSA */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_import.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2005/06/03 18:48:28 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_make_key.c b/libtomcrypt/src/pk/rsa/rsa_make_key.c
new file mode 100644
index 0000000..d874106
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_make_key.c
@@ -0,0 +1,125 @@
+/* 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 rsa_make_key.c
+ RSA key generation, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ Create an RSA key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param size The size of the modulus (key size) desired (octets)
+ @param e The "e" value (public key). e==65537 is a good choice
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+*/
+int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
+{
+ mp_int p, q, tmp1, tmp2, tmp3;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+
+ if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if ((e < 3) || ((e & 1) == 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ /* make primes p and q (optimization provided by Wayne Scott) */
+ if ((err = mp_set_int(&tmp3, e)) != MP_OKAY) { goto error; } /* tmp3 = e */
+
+ /* make prime "p" */
+ do {
+ if ((err = rand_prime(&p, size*4, prng, wprng)) != CRYPT_OK) { goto done; }
+ if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = p-1 */
+ if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = gcd(p-1, e) */
+ } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides p-1 */
+
+ /* make prime "q" */
+ do {
+ if ((err = rand_prime(&q, size*4, prng, wprng)) != CRYPT_OK) { goto done; }
+ if ((err = mp_sub_d(&q, 1, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = q-1 */
+ if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = gcd(q-1, e) */
+ } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides q-1 */
+
+ /* tmp1 = lcm(p-1, q-1) */
+ if ((err = mp_sub_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p-1 */
+ /* tmp1 = q-1 (previous do/while loop) */
+ if ((err = mp_lcm(&tmp1, &tmp2, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = lcm(p-1, q-1) */
+
+ /* make key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
+ &key->qP, &key->p, &key->q, NULL)) != MP_OKAY) {
+ goto error;
+ }
+
+ if ((err = mp_set_int(&key->e, e)) != MP_OKAY) { goto error2; } /* key->e = e */
+ if ((err = mp_invmod(&key->e, &tmp1, &key->d)) != MP_OKAY) { goto error2; } /* key->d = 1/e mod lcm(p-1,q-1) */
+ if ((err = mp_mul(&p, &q, &key->N)) != MP_OKAY) { goto error2; } /* key->N = pq */
+
+ /* optimize for CRT now */
+ /* find d mod q-1 and d mod p-1 */
+ if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY) { goto error2; } /* tmp1 = q-1 */
+ if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY) { goto error2; } /* tmp2 = p-1 */
+ if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY) { goto error2; } /* dP = d mod p-1 */
+ if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY) { goto error2; } /* dQ = d mod q-1 */
+ if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY) { goto error2; } /* qP = 1/q mod p */
+
+ if ((err = mp_copy(&p, &key->p)) != MP_OKAY) { goto error2; }
+ if ((err = mp_copy(&q, &key->q)) != MP_OKAY) { goto error2; }
+
+ /* shrink ram required */
+ if ((err = mp_shrink(&key->e)) != MP_OKAY) { goto error2; }
+ if ((err = mp_shrink(&key->d)) != MP_OKAY) { goto error2; }
+ if ((err = mp_shrink(&key->N)) != MP_OKAY) { goto error2; }
+ if ((err = mp_shrink(&key->dQ)) != MP_OKAY) { goto error2; }
+ if ((err = mp_shrink(&key->dP)) != MP_OKAY) { goto error2; }
+ if ((err = mp_shrink(&key->qP)) != MP_OKAY) { goto error2; }
+ if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error2; }
+ if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error2; }
+
+ /* set key type (in this case it's CRT optimized) */
+ key->type = PK_PRIVATE;
+
+ /* return ok and free temps */
+ err = CRYPT_OK;
+ goto done;
+error2:
+ mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
+ &key->qP, &key->p, &key->q, NULL);
+error:
+ err = mpi_to_ltc_error(err);
+done:
+ mp_clear_multi(&tmp3, &tmp2, &tmp1, &p, &q, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_make_key.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_sign_hash.c b/libtomcrypt/src/pk/rsa/rsa_sign_hash.c
new file mode 100644
index 0000000..d31bda3
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_sign_hash.c
@@ -0,0 +1,79 @@
+/* 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 rsa_sign_hash.c
+ RSA PKCS v2 PSS sign hash, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ (PKCS #1, v2.0) PSS pad then sign
+ @param in The hash to sign
+ @param inlen The length of the hash to sign (octets)
+ @param out [out] The signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param prng_idx The index of the PRNG desired
+ @param hash_idx The index of the hash desired
+ @param saltlen The length of the salt desired (octets)
+ @param key The private RSA key to use
+ @return CRYPT_OK if successful
+*/
+int rsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int prng_idx,
+ int hash_idx, unsigned long saltlen,
+ rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid prng and hash ? */
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits(&(key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+ if (modulus_bytelen > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* PSS pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx,
+ hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* RSA encode it */
+ return rsa_exptmod(out, x, out, outlen, PK_PRIVATE, key);
+}
+
+#endif /* MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_sign_hash.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/libtomcrypt/src/pk/rsa/rsa_verify_hash.c b/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
new file mode 100644
index 0000000..690364d
--- /dev/null
+++ b/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
@@ -0,0 +1,86 @@
+/* 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 rsa_verify_hash.c
+ RSA PKCS v2 PSS signature verification, Tom St Denis
+*/
+
+#ifdef MRSA
+
+/**
+ (PKCS #1, v2.0) de-sign then PSS depad
+ @param sig The signature data
+ @param siglen The length of the signature data (octets)
+ @param hash The hash of the message that was signed
+ @param hashlen The length of the hash of the message that was signed (octets)
+ @param hash_idx The index of the desired hash
+ @param saltlen The length of the salt used during signature
+ @param stat [out] The result of the signature comparison, 1==valid, 0==invalid
+ @param key The public RSA key corresponding to the key that performed the signature
+ @return CRYPT_OK on success (even if the signature is invalid)
+*/
+int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int hash_idx, unsigned long saltlen,
+ int *stat, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmpbuf;
+
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits(&(key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+ if (modulus_bytelen != siglen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate temp buffer for decoded sig */
+ tmpbuf = XMALLOC(siglen);
+ if (tmpbuf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* RSA decode it */
+ x = siglen;
+ if ((err = rsa_exptmod(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {
+ XFREE(tmpbuf);
+ return err;
+ }
+
+ /* PSS decode it */
+ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
+ XFREE(tmpbuf);
+ return err;
+}
+
+#endif /* MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_verify_hash.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */