summaryrefslogtreecommitdiff
path: root/src/ltc/pk
diff options
context:
space:
mode:
Diffstat (limited to 'src/ltc/pk')
-rw-r--r--src/ltc/pk/asn1/der/bit/der_decode_bit_string.c25
-rw-r--r--src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c25
-rw-r--r--src/ltc/pk/asn1/der/bit/der_encode_bit_string.c13
-rw-r--r--src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c13
-rw-r--r--src/ltc/pk/asn1/der/bit/der_length_bit_string.c18
-rw-r--r--src/ltc/pk/asn1/der/choice/der_decode_choice.c12
-rw-r--r--src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c420
-rw-r--r--src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c238
-rw-r--r--src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c213
-rw-r--r--src/ltc/pk/asn1/der/general/der_asn1_maps.c167
-rw-r--r--src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c133
-rw-r--r--src/ltc/pk/asn1/der/general/der_decode_asn1_length.c67
-rw-r--r--src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.c97
-rw-r--r--src/ltc/pk/asn1/der/general/der_encode_asn1_length.c127
-rw-r--r--src/ltc/pk/asn1/der/general/der_length_asn1_identifier.c33
-rw-r--r--src/ltc/pk/asn1/der/general/der_length_asn1_length.c32
-rw-r--r--src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c25
-rw-r--r--src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c20
-rw-r--r--src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c18
-rw-r--r--src/ltc/pk/asn1/der/integer/der_decode_integer.c48
-rw-r--r--src/ltc/pk/asn1/der/integer/der_encode_integer.c23
-rw-r--r--src/ltc/pk/asn1/der/integer/der_length_integer.c26
-rw-r--r--src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c46
-rw-r--r--src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c15
-rw-r--r--src/ltc/pk/asn1/der/octet/der_decode_octet_string.c24
-rw-r--r--src/ltc/pk/asn1/der/octet/der_encode_octet_string.c20
-rw-r--r--src/ltc/pk/asn1/der/octet/der_length_octet_string.c20
-rw-r--r--src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c25
-rw-r--r--src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c20
-rw-r--r--src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c18
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c310
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c213
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c83
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c56
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c6
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_length_sequence.c51
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c2
-rw-r--r--src/ltc/pk/asn1/der/set/der_encode_set.c25
-rw-r--r--src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c24
-rw-r--r--src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c25
-rw-r--r--src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c18
-rw-r--r--src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c38
-rw-r--r--src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c43
-rw-r--r--src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c18
-rw-r--r--src/ltc/pk/asn1/x509/x509_decode_subject_public_key_info.c (renamed from src/ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.c)27
-rw-r--r--src/ltc/pk/asn1/x509/x509_encode_subject_public_key_info.c (renamed from src/ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.c)8
-rw-r--r--src/ltc/pk/dsa/dsa_export.c2
-rw-r--r--src/ltc/pk/dsa/dsa_import.c7
-rw-r--r--src/ltc/pk/dsa/dsa_verify_hash.c2
-rw-r--r--src/ltc/pk/ecc/ecc.c333
-rw-r--r--src/ltc/pk/ecc/ecc_ansi_x963_export.c8
-rw-r--r--src/ltc/pk/ecc/ecc_ansi_x963_import.c64
-rw-r--r--src/ltc/pk/ecc/ecc_decrypt_key.c11
-rw-r--r--src/ltc/pk/ecc/ecc_dp_clear.c36
-rw-r--r--src/ltc/pk/ecc/ecc_dp_fill_from_sets.c76
-rw-r--r--src/ltc/pk/ecc/ecc_dp_from_oid.c84
-rw-r--r--src/ltc/pk/ecc/ecc_dp_from_params.c84
-rw-r--r--src/ltc/pk/ecc/ecc_dp_init.c36
-rw-r--r--src/ltc/pk/ecc/ecc_dp_set.c100
-rw-r--r--src/ltc/pk/ecc/ecc_encrypt_key.c15
-rw-r--r--src/ltc/pk/ecc/ecc_export.c9
-rw-r--r--src/ltc/pk/ecc/ecc_export_openssl.c (renamed from src/ltc/pk/ecc/ecc_export_full.c)81
-rw-r--r--src/ltc/pk/ecc/ecc_free.c12
-rw-r--r--src/ltc/pk/ecc/ecc_get_key.c (renamed from src/ltc/pk/ecc/ecc_export_raw.c)28
-rw-r--r--src/ltc/pk/ecc/ecc_get_set.c40
-rw-r--r--src/ltc/pk/ecc/ecc_get_size.c12
-rw-r--r--src/ltc/pk/ecc/ecc_import.c42
-rw-r--r--src/ltc/pk/ecc/ecc_import_full.c152
-rw-r--r--src/ltc/pk/ecc/ecc_import_openssl.c157
-rw-r--r--src/ltc/pk/ecc/ecc_import_pkcs8.c696
-rw-r--r--src/ltc/pk/ecc/ecc_import_raw.c100
-rw-r--r--src/ltc/pk/ecc/ecc_import_x509.c59
-rw-r--r--src/ltc/pk/ecc/ecc_make_key.c99
-rw-r--r--src/ltc/pk/ecc/ecc_set_dp.c97
-rw-r--r--src/ltc/pk/ecc/ecc_set_dp_internal.c150
-rw-r--r--src/ltc/pk/ecc/ecc_set_key.c67
-rw-r--r--src/ltc/pk/ecc/ecc_shared_secret.c25
-rw-r--r--src/ltc/pk/ecc/ecc_sign_hash.c45
-rw-r--r--src/ltc/pk/ecc/ecc_sizes.c36
-rw-r--r--src/ltc/pk/ecc/ecc_verify_hash.c85
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_export_point.c9
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_import_point.c9
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_is_point.c43
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c6
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c42
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_map.c5
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_mul2add.c25
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_mulmod.c48
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c43
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_points.c3
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_projective_add_point.c7
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c11
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_verify_key.c (renamed from src/ltc/pk/ecc/ecc_verify_key.c)31
-rw-r--r--src/ltc/pk/rsa/rsa_export.c2
-rw-r--r--src/ltc/pk/rsa/rsa_import.c7
-rw-r--r--src/ltc/pk/rsa/rsa_import_x509.c7
-rw-r--r--src/ltc/pk/rsa/rsa_verify_hash.c4
97 files changed, 3617 insertions, 2463 deletions
diff --git a/src/ltc/pk/asn1/der/bit/der_decode_bit_string.c b/src/ltc/pk/asn1/der/bit/der_decode_bit_string.c
index 5203fcfd..6f25cd9a 100644
--- a/src/ltc/pk/asn1/der/bit/der_decode_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_decode_bit_string.c
@@ -28,6 +28,7 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long dlen, blen, x, y;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -47,27 +48,13 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
x = 1;
/* get the length of the data */
- if (in[x] & 0x80) {
- /* long format get number of length bytes */
- y = in[x++] & 0x7F;
-
- /* invalid if 0 or > 2 */
- if (y == 0 || y > 2) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the data len */
- dlen = 0;
- while (y--) {
- dlen = (dlen << 8) | (unsigned long)in[x++];
- }
- } else {
- /* short format */
- dlen = in[x++] & 0x7F;
+ y = inlen - 1;
+ if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
+ return err;
}
-
+ x += y;
/* is the data len too long or too short? */
- if ((dlen == 0) || (dlen + x > inlen)) {
+ if ((dlen == 0) || (dlen > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c b/src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c
index 223899b3..7e7a4608 100644
--- a/src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c
@@ -31,6 +31,7 @@ int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long dlen, blen, x, y;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -50,27 +51,13 @@ int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
x = 1;
/* get the length of the data */
- if (in[x] & 0x80) {
- /* long format get number of length bytes */
- y = in[x++] & 0x7F;
-
- /* invalid if 0 or > 2 */
- if (y == 0 || y > 2) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the data len */
- dlen = 0;
- while (y--) {
- dlen = (dlen << 8) | (unsigned long)in[x++];
- }
- } else {
- /* short format */
- dlen = in[x++] & 0x7F;
+ y = inlen - 1;
+ if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
+ return err;
}
-
+ x += y;
/* is the data len too long or too short? */
- if ((dlen == 0) || (dlen + x > inlen)) {
+ if ((dlen == 0) || (dlen > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/bit/der_encode_bit_string.c b/src/ltc/pk/asn1/der/bit/der_encode_bit_string.c
index 2a674790..7b2c6afa 100644
--- a/src/ltc/pk/asn1/der/bit/der_encode_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_encode_bit_string.c
@@ -50,16 +50,11 @@ int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
y = ((inlen + 7) >> 3) + 1;
out[x++] = 0x03;
- if (y < 128) {
- out[x++] = (unsigned char)y;
- } else if (y < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)y;
- } else if (y < 65536) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((y>>8)&255);
- out[x++] = (unsigned char)(y&255);
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store number of zero padding bits */
out[x++] = (unsigned char)((8 - inlen) & 7);
diff --git a/src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c b/src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c
index 4101a1da..e884dabe 100644
--- a/src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c
@@ -52,16 +52,11 @@ int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen,
y = ((inlen + 7) >> 3) + 1;
out[x++] = 0x03;
- if (y < 128) {
- out[x++] = (unsigned char)y;
- } else if (y < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)y;
- } else if (y < 65536) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((y>>8)&255);
- out[x++] = (unsigned char)(y&255);
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store number of zero padding bits */
out[x++] = (unsigned char)((8 - inlen) & 7);
diff --git a/src/ltc/pk/asn1/der/bit/der_length_bit_string.c b/src/ltc/pk/asn1/der/bit/der_length_bit_string.c
index b9c99fb1..7a652084 100644
--- a/src/ltc/pk/asn1/der/bit/der_length_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_length_bit_string.c
@@ -22,24 +22,18 @@
*/
int der_length_bit_string(unsigned long nbits, unsigned long *outlen)
{
- unsigned long nbytes;
+ unsigned long nbytes, x;
+ int err;
+
LTC_ARGCHK(outlen != NULL);
/* get the number of the bytes */
nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;
- if (nbytes < 128) {
- /* 03 LL PP DD DD DD ... */
- *outlen = 2 + nbytes;
- } else if (nbytes < 256) {
- /* 03 81 LL PP DD DD DD ... */
- *outlen = 3 + nbytes;
- } else if (nbytes < 65536) {
- /* 03 82 LL LL PP DD DD DD ... */
- *outlen = 4 + nbytes;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(nbytes, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + nbytes;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/choice/der_decode_choice.c b/src/ltc/pk/asn1/der/choice/der_decode_choice.c
index 0bfd3bb6..6e17a4b7 100644
--- a/src/ltc/pk/asn1/der/choice/der_decode_choice.c
+++ b/src/ltc/pk/asn1/der/choice/der_decode_choice.c
@@ -205,9 +205,17 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen,
}
break;
+ case LTC_ASN1_CUSTOM_TYPE:
+ if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) {
+ if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_EOL:
return CRYPT_INVALID_ARG;
}
diff --git a/src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c b/src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c
new file mode 100644
index 00000000..9bc34312
--- /dev/null
+++ b/src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c
@@ -0,0 +1,420 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+
+/**
+ @file der_decode_custom_type.c
+ ASN.1 DER, decode a Custom type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a Custom type
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param root The item that defines the custom type to decode
+ @return CRYPT_OK on success
+*/
+int der_decode_custom_type(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root)
+{
+ LTC_ARGCHK(root != NULL);
+ return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED);
+}
+
+/**
+ Extended-decode a Custom type
+
+ This function is used to decode custom types and sequences/sets
+ For custom types root is used
+ For sequences/sets list and outlen are used
+
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param root The item that defines the custom type to decode
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @param flags c.f. enum ltc_der_seq
+ @return CRYPT_OK on success
+*/
+int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root,
+ ltc_asn1_list *list, unsigned long outlen,
+ unsigned int flags)
+{
+ int err, seq_err, i, ordered;
+ ltc_asn1_type type;
+ ltc_asn1_list ident;
+ unsigned long size, x, y, z, blksize;
+ unsigned char* in_new = NULL;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+
+ /* get blk size */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 0;
+
+ if (root == NULL) {
+ LTC_ARGCHK(list != NULL);
+
+ /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
+ if (in[x] != 0x30 && in[x] != 0x31) {
+ return CRYPT_INVALID_PACKET;
+ }
+ ++x;
+ } else {
+ if (root->type != LTC_ASN1_CUSTOM_TYPE) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* Alloc a copy of the data for primitive handling. */
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ in_new = XMALLOC(inlen);
+ if (in_new == NULL) {
+ return CRYPT_MEM;
+ }
+ XMEMCPY(in_new, in, inlen);
+ in = in_new;
+ }
+
+ y = inlen;
+ if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((ident.type != root->type) ||
+ (ident.class != root->class) ||
+ (ident.pc != root->pc) ||
+ (ident.tag != root->tag)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ x += y;
+
+ list = root->data;
+ outlen = root->size;
+ }
+
+ if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) ||
+ (der_asn1_type_to_identifier_map[root->used] == -1)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ root->type = (ltc_asn1_type)root->used;
+ list = root;
+ outlen = 1;
+
+ x -= 1;
+ in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type];
+ blksize = inlen - x;
+ } else {
+
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += y;
+ }
+
+ /* would this blksize overflow? */
+ if (blksize > (inlen - x)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* mark all as unused */
+ for (i = 0; i < (int)outlen; i++) {
+ list[i].used = 0;
+ }
+ ordered = flags & LTC_DER_SEQ_ORDERED;
+
+ /* ok read data */
+ seq_err = CRYPT_OK;
+ blksize += x;
+ inlen -= x;
+ for (i = 0; i < (int)outlen; i++) {
+ z = 0;
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+ if (!ordered && list[i].used == 1) { continue; }
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto LBL_ERR;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = inlen;
+ if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_boolean(&z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = inlen;
+ if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = inlen;
+ if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_RAW_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = inlen;
+ if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
+ if (!ordered || list[i].optional) { continue; }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = inlen;
+ if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_TELETEX_STRING:
+ z = inlen;
+ if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = inlen;
+ if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = inlen;
+ if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = inlen;
+ if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = inlen;
+ if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ z = inlen;
+ if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = inlen;
+ if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ /* detect if we have the right type */
+ if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ z = inlen;
+ err = der_decode_sequence_ex(in + x, z, data, size, flags);
+ if (err == CRYPT_INPUT_TOO_LONG) {
+ seq_err = CRYPT_INPUT_TOO_LONG;
+ err = CRYPT_OK;
+ }
+ if (err != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = inlen;
+ err = der_decode_custom_type(in + x, z, &list[i]);
+ if (err == CRYPT_INPUT_TOO_LONG) {
+ seq_err = CRYPT_INPUT_TOO_LONG;
+ err = CRYPT_OK;
+ }
+ if (err != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CHOICE:
+ z = inlen;
+ if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_EOL:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ list[i].used = 1;
+ if (!ordered) {
+ /* restart the decoder */
+ i = -1;
+ }
+ }
+
+ for (i = 0; i < (int)outlen; i++) {
+ if (list[i].used == 0 && list[i].optional == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+
+ if (blksize == x && seq_err == CRYPT_OK && inlen == 0) {
+ /* everything decoded and no errors in nested sequences */
+ err = CRYPT_OK;
+ } else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) {
+ /* a sequence reported too-long input, but now we've decoded everything */
+ err = CRYPT_OK;
+ } else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) {
+ err = CRYPT_INVALID_PACKET;
+ } else {
+ err = CRYPT_INPUT_TOO_LONG;
+ }
+
+LBL_ERR:
+ if (in_new != NULL) {
+ XFREE(in_new);
+ }
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c b/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c
new file mode 100644
index 00000000..d19774c4
--- /dev/null
+++ b/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c
@@ -0,0 +1,238 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+
+/**
+ @file der_encode_custom_type.c
+ ASN.1 DER, encode a Custom Type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a Custom Type
+
+ This function is a bit special compared to the others, as it requires the
+ root-ltc_asn1_list where the type is defined.
+
+ @param root The root of the list of items to encode
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_custom_type(const ltc_asn1_list *root,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ ltc_asn1_type type;
+ const ltc_asn1_list *list;
+ unsigned long size, x, y, z, i, inlen, id_len;
+ void *data;
+
+ LTC_ARGCHK(root != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0; z = 0;
+ if ((err = der_length_custom_type(root, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG;
+
+ /* too big ? */
+ if (*outlen < y) {
+ *outlen = y;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* get length of the identifier, so we know the offset where to start writing */
+ if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) return CRYPT_INVALID_ARG;
+ x = id_len;
+
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ list = root;
+ inlen = 1;
+ /* In case it's a PRIMITIVE type we encode directly to the output
+ * but leave space for a potentially longer identifier as it will
+ * simply be replaced afterwards.
+ */
+ x -= 1;
+ } else {
+ list = root->data;
+ inlen = root->size;
+ /* store length, identifier will be added later */
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += y;
+ }
+
+ /* store data */
+ *outlen -= x;
+ for (i = 0; i < inlen; i++) {
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ type = (ltc_asn1_type)list[i].used;
+ } else {
+ type = list[i].type;
+ }
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = *outlen;
+ if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_RAW_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = *outlen;
+ if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ out[x] = 0x05;
+ out[x+1] = 0x00;
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = *outlen;
+ if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = *outlen;
+ if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = *outlen;
+ if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = *outlen;
+ if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *outlen;
+ if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ z = *outlen;
+ if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = *outlen;
+ if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ z = *outlen;
+ if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SEQUENCE:
+ z = *outlen;
+ if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = *outlen;
+ if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ case LTC_ASN1_TELETEX_STRING:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+
+ x += z;
+ *outlen -= z;
+ }
+
+ if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ *outlen = x;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c b/src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c
new file mode 100644
index 00000000..aecc4647
--- /dev/null
+++ b/src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c
@@ -0,0 +1,213 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_custom_type.c
+ ASN.1 DER, length of a custom type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER custom type
+
+ This function is a bit special compared to the others, as it requires the
+ root-ltc_asn1_list where the type is defined.
+
+ @param root The root of the struct to encode
+ @param outlen [out] The length required in octets to store it
+ @param payloadlen [out] The length of the payload in octets
+ @return CRYPT_OK on success
+*/
+int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen)
+{
+ int err;
+ const ltc_asn1_list *list;
+ ltc_asn1_type type;
+ unsigned long size, x, y, i, inlen, id_len;
+ void *data;
+
+ LTC_ARGCHK(root != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) {
+ return err;
+ }
+ y = id_len;
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ list = root;
+ inlen = 1;
+ } else {
+ list = root->data;
+ inlen = root->size;
+ }
+ for (i = 0; i < inlen; i++) {
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ type = (ltc_asn1_type)list[i].used;
+ } else {
+ type = list[i].type;
+ }
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ /* some items may be optional during import */
+ if (!list[i].used && list[i].optional) continue;
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_RAW_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_TELETEX_STRING:
+ if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ /* In case it's a PRIMITIVE element we're going
+ * to only replace the identifier of the one element
+ * by the custom identifier.
+ */
+ y -= 1;
+ if (payloadlen != NULL) {
+ *payloadlen = y - id_len;
+ }
+ } else {
+ /* calc length of length */
+ if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if (payloadlen != NULL) {
+ *payloadlen = y - id_len;
+ }
+ y += x;
+ }
+
+ /* store size */
+ *outlen = y;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_asn1_maps.c b/src/ltc/pk/asn1/der/general/der_asn1_maps.c
new file mode 100644
index 00000000..ba9820f4
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_asn1_maps.c
@@ -0,0 +1,167 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_asn1_maps.c
+ ASN.1 DER, a collection of maps to convert between different representations, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ A Map from ltc_asn1_type to the regularly used ASN.1 identifier
+*/
+const int der_asn1_type_to_identifier_map[] =
+{
+ /* 0 */
+ -1, /* LTC_ASN1_EOL, */
+ 1, /* LTC_ASN1_BOOLEAN, */
+ 2, /* LTC_ASN1_INTEGER, */
+ 2, /* LTC_ASN1_SHORT_INTEGER, */
+ 3, /* LTC_ASN1_BIT_STRING, */
+ /* 5 */
+ 4, /* LTC_ASN1_OCTET_STRING, */
+ 5, /* LTC_ASN1_NULL, */
+ 6, /* LTC_ASN1_OBJECT_IDENTIFIER, */
+ 22, /* LTC_ASN1_IA5_STRING, */
+ 19, /* LTC_ASN1_PRINTABLE_STRING, */
+ /* 10 */
+ 12, /* LTC_ASN1_UTF8_STRING, */
+ 23, /* LTC_ASN1_UTCTIME, */
+ -1, /* LTC_ASN1_CHOICE, */
+ 48, /* LTC_ASN1_SEQUENCE, */
+ 49, /* LTC_ASN1_SET, */
+ /* 15 */
+ 49, /* LTC_ASN1_SETOF, */
+ 3, /* LTC_ASN1_RAW_BIT_STRING, */
+ 20, /* LTC_ASN1_TELETEX_STRING, */
+ 24, /* LTC_ASN1_GENERALIZEDTIME, */
+ -1, /* LTC_ASN1_CUSTOM_TYPE, */
+};
+const unsigned long der_asn1_type_to_identifier_map_sz = sizeof(der_asn1_type_to_identifier_map)/sizeof(der_asn1_type_to_identifier_map[0]);
+
+/**
+ A Map from the ASN.1 Class to its string
+*/
+const char* der_asn1_class_to_string_map[] =
+{
+ "UNIVERSAL",
+ "APPLICATION",
+ "CONTEXT-SPECIFIC",
+ "PRIVATE",
+};
+const unsigned long der_asn1_class_to_string_map_sz = sizeof(der_asn1_class_to_string_map)/sizeof(der_asn1_class_to_string_map[0]);
+
+/**
+ A Map from the ASN.1 P/C-bit to its string
+*/
+const char* der_asn1_pc_to_string_map[] =
+{
+ "PRIMITIVE",
+ "CONSTRUCTED",
+};
+const unsigned long der_asn1_pc_to_string_map_sz = sizeof(der_asn1_pc_to_string_map)/sizeof(der_asn1_pc_to_string_map[0]);
+
+/**
+ A Map from the ASN.1 tag to its string
+*/
+const char* der_asn1_tag_to_string_map[] =
+{
+ "Reserved for use by the encoding rules",
+ "Boolean type",
+ "Integer type",
+ "Bitstring type",
+ "Octetstring type",
+ "Null type",
+ "Object identifier type",
+ "Object descriptor type",
+ "External type and Instance-of type",
+ "Real type",
+ "Enumerated type",
+ "Embedded-pdv type",
+ "UTF8String type",
+ "Relative object identifier type",
+ "The time type",
+ "Reserved for future editions of this Recommendation | International Standard",
+ "Sequence and Sequence-of types",
+ "Set and Set-of types",
+ "NumericString type",
+ "PrintableString type",
+ "TeletexString (T61String) type",
+ "VideotexString type",
+ "IA5String type",
+ "UTCTime type",
+ "GeneralizedTime type",
+ "GraphicString type",
+ "VisibleString (ISO646String) type",
+ "GeneralString type",
+ "UniversalString type",
+ "UnrestrictedCharacterString type",
+ "BMPString type",
+ "Date type",
+ "TimeOfDay type",
+ "DateTime type",
+ "Duration type",
+ "OID internationalized resource identifier type",
+ "Relative OID internationalized resource identifier type",
+};
+const unsigned long der_asn1_tag_to_string_map_sz = sizeof(der_asn1_tag_to_string_map)/sizeof(der_asn1_tag_to_string_map[0]);
+
+/**
+ A Map from ASN.1 Tags to ltc_asn1_type
+*/
+const ltc_asn1_type der_asn1_tag_to_type_map[] =
+{
+ /* 0 */
+ LTC_ASN1_EOL, /* Reserved for use by the encoding rules */
+ LTC_ASN1_BOOLEAN, /* Boolean type */
+ LTC_ASN1_INTEGER, /* Integer type */
+ LTC_ASN1_BIT_STRING, /* Bitstring type */
+ LTC_ASN1_OCTET_STRING, /* Octetstring type */
+ /* 5 */
+ LTC_ASN1_NULL, /* Null type */
+ LTC_ASN1_OBJECT_IDENTIFIER, /* Object identifier type */
+ LTC_ASN1_CUSTOM_TYPE, /* Object descriptor type */
+ LTC_ASN1_CUSTOM_TYPE, /* External type and Instance-of type */
+ LTC_ASN1_CUSTOM_TYPE, /* Real type */
+ /* 10 */
+ LTC_ASN1_CUSTOM_TYPE, /* Enumerated type */
+ LTC_ASN1_CUSTOM_TYPE, /* Embedded-pdv type */
+ LTC_ASN1_UTF8_STRING, /* UTF8String type */
+ LTC_ASN1_CUSTOM_TYPE, /* Relative object identifier type */
+ LTC_ASN1_CUSTOM_TYPE, /* The time type */
+ /* 15 */
+ LTC_ASN1_EOL, /* Reserved for future editions of this Recommendation | International Standard */
+ LTC_ASN1_SEQUENCE, /* Sequence and Sequence-of types */
+ LTC_ASN1_SET, /* Set and Set-of types */
+ LTC_ASN1_CUSTOM_TYPE, /* NumericString types */
+ LTC_ASN1_PRINTABLE_STRING, /* PrintableString types */
+ /* 20 */
+ LTC_ASN1_TELETEX_STRING, /* TeletexString (T61String) types */
+ LTC_ASN1_CUSTOM_TYPE, /* VideotexString types */
+ LTC_ASN1_IA5_STRING, /* IA5String types */
+ LTC_ASN1_UTCTIME, /* UTCTime types */
+ LTC_ASN1_GENERALIZEDTIME, /* GeneralizedTime types */
+ /* 25 */
+ LTC_ASN1_CUSTOM_TYPE, /* GraphicString types */
+ LTC_ASN1_CUSTOM_TYPE, /* VisibleString (ISO646String) types */
+ LTC_ASN1_CUSTOM_TYPE, /* GeneralString types */
+ LTC_ASN1_CUSTOM_TYPE, /* UniversalString types */
+ LTC_ASN1_CUSTOM_TYPE, /* UnrestrictedCharacterString types */
+ /* 30 */
+ LTC_ASN1_CUSTOM_TYPE, /* BMPString types */
+};
+const unsigned long der_asn1_tag_to_type_map_sz = sizeof(der_asn1_tag_to_type_map)/sizeof(der_asn1_tag_to_type_map[0]);
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c b/src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c
new file mode 100644
index 00000000..b4689f6a
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c
@@ -0,0 +1,133 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_asn1_identifier.c
+ ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */
+static const unsigned char tag_constructed_map[] =
+{
+ /* 0 */
+ 255,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 5 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 10 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 15 */
+ 255,
+ LTC_ASN1_PC_CONSTRUCTED,
+ LTC_ASN1_PC_CONSTRUCTED,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 20 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 25 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+};
+ static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]);
+
+/**
+ Decode the ASN.1 Identifier
+ @param id Where to store the decoded Identifier
+ @param in Where to read the Identifier from
+ @param inlen [in/out] The size of in available/read
+ @return CRYPT_OK if successful
+*/
+int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id)
+{
+ ulong64 tmp;
+ unsigned long tag_len;
+ int err;
+
+ LTC_ARGCHK(id != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+
+ if (*inlen == 0) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ tag_len = 1;
+ id->class = (in[0] >> 6) & 0x3;
+ id->pc = (in[0] >> 5) & 0x1;
+ id->tag = in[0] & 0x1f;
+
+ err = CRYPT_OK;
+ if (id->tag == 0x1f) {
+ id->tag = 0;
+ do {
+ if (*inlen < tag_len) {
+ /* break the loop and trigger the BOF error-code */
+ tmp = 0xff;
+ break;
+ }
+ id->tag <<= 7;
+ id->tag |= in[tag_len] & 0x7f;
+ tmp = in[tag_len] & 0x80;
+ tag_len++;
+ } while ((tmp != 0) && (tag_len < 10));
+
+ if (tmp != 0) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else if (id->tag < 0x1f) {
+ err = CRYPT_PK_ASN1_ERROR;
+ }
+ }
+
+ if (err != CRYPT_OK) {
+ id->pc = 0;
+ id->class = 0;
+ id->tag = 0;
+ } else {
+ *inlen = tag_len;
+ if ((id->class == LTC_ASN1_CL_UNIVERSAL) &&
+ (id->tag < der_asn1_tag_to_type_map_sz) &&
+ (id->tag < tag_constructed_map_sz) &&
+ (id->pc == tag_constructed_map[id->tag])) {
+ id->type = der_asn1_tag_to_type_map[id->tag];
+ } else {
+ if ((id->class == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) {
+ id->type = LTC_ASN1_EOL;
+ } else {
+ id->type = LTC_ASN1_CUSTOM_TYPE;
+ }
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_decode_asn1_length.c b/src/ltc/pk/asn1/der/general/der_decode_asn1_length.c
new file mode 100644
index 00000000..0e1bc6c2
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_decode_asn1_length.c
@@ -0,0 +1,67 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_asn1_length.c
+ ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Decode the ASN.1 Length field
+ @param in Where to read the length field from
+ @param inlen [in/out] The size of in available/read
+ @param outlen [out] The decoded ASN.1 length
+ @return CRYPT_OK if successful
+*/
+int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen)
+{
+ unsigned long real_len, decoded_len, offset, i;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+
+ if (*inlen < 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ real_len = in[0];
+
+ if (real_len < 128) {
+ decoded_len = real_len;
+ offset = 1;
+ } else {
+ real_len &= 0x7F;
+ if (real_len == 0) {
+ return CRYPT_PK_ASN1_ERROR;
+ } else if (real_len > sizeof(decoded_len)) {
+ return CRYPT_OVERFLOW;
+ } else if (real_len > (*inlen - 1)) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ decoded_len = 0;
+ offset = 1 + real_len;
+ for (i = 0; i < real_len; i++) {
+ decoded_len = (decoded_len << 8) | in[1 + i];
+ }
+ }
+
+ if (outlen != NULL) *outlen = decoded_len;
+ if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW;
+ *inlen = offset;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.c b/src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.c
new file mode 100644
index 00000000..367bb699
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.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.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_asn1_identifier.c
+ ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Encode the ASN.1 Identifier
+ @param id The ASN.1 Identifer to encode
+ @param out Where to write the identifier to
+ @param outlen [in/out] The size of out available/written
+ @return CRYPT_OK if successful
+*/
+int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen)
+{
+ ulong64 tmp;
+ unsigned long tag_len;
+
+ LTC_ARGCHK(id != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (id->type != LTC_ASN1_CUSTOM_TYPE) {
+ if ((unsigned)id->type >= der_asn1_type_to_identifier_map_sz) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (der_asn1_type_to_identifier_map[id->type] == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (out != NULL) {
+ *out = der_asn1_type_to_identifier_map[id->type];
+ }
+ *outlen = 1;
+ return CRYPT_OK;
+ } else {
+ if (id->class < LTC_ASN1_CL_UNIVERSAL || id->class > LTC_ASN1_CL_PRIVATE) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (id->tag > (ULONG_MAX >> (8 + 7))) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (out != NULL) {
+ if (*outlen < 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ out[0] = id->class << 6 | id->pc << 5;
+ }
+
+ if (id->tag < 0x1f) {
+ if (out != NULL) {
+ out[0] |= id->tag & 0x1f;
+ }
+ *outlen = 1;
+ } else {
+ tag_len = 0;
+ tmp = id->tag;
+ do {
+ tag_len++;
+ tmp >>= 7;
+ } while (tmp);
+
+ if (out != NULL) {
+ if (*outlen < tag_len + 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ out[0] |= 0x1f;
+ for (tmp = 1; tmp <= tag_len; ++tmp) {
+ out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80;
+ }
+ out[tag_len] &= ~0x80;
+ }
+ *outlen = tag_len + 1;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_encode_asn1_length.c b/src/ltc/pk/asn1/der/general/der_encode_asn1_length.c
new file mode 100644
index 00000000..0d871afe
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_encode_asn1_length.c
@@ -0,0 +1,127 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_asn1_length.c
+ ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Encode the ASN.1 length field
+ @param len The length to encode
+ @param out Where to write the length field to
+ @param outlen [in/out] The size of out available/written
+ @return CRYPT_OK if successful
+*/
+int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ x = len;
+ y = 0;
+
+ while(x != 0) {
+ y++;
+ x >>= 8;
+ }
+ if (y == 0) {
+ return CRYPT_PK_ASN1_ERROR;
+ }
+
+ if (out == NULL) {
+ if (len < 128) {
+ x = y;
+ } else {
+ x = y + 1;
+ }
+ } else {
+ if (*outlen < y) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ x = 0;
+ if (len < 128) {
+ out[x++] = (unsigned char)len;
+ } else if (len <= 0xffUL) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)len;
+ } else if (len <= 0xffffUL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffUL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ #if ULONG_MAX != ULLONG_MAX
+ } else {
+ out[x++] = 0x84;
+ out[x++] = (unsigned char)((len>>24UL)&255);
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ }
+ #else
+ } else if (len <= 0xffffffffUL) {
+ out[x++] = 0x84;
+ out[x++] = (unsigned char)((len>>24UL)&255);
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffULL) {
+ out[x++] = 0x85;
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffffULL) {
+ out[x++] = 0x86;
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffffffULL) {
+ out[x++] = 0x87;
+ out[x++] = (unsigned char)((len>>48ULL)&255);
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else {
+ out[x++] = 0x88;
+ out[x++] = (unsigned char)((len>>56ULL)&255);
+ out[x++] = (unsigned char)((len>>48ULL)&255);
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ }
+ #endif
+ }
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_length_asn1_identifier.c b/src/ltc/pk/asn1/der/general/der_length_asn1_identifier.c
new file mode 100644
index 00000000..40e76f02
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_length_asn1_identifier.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.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_asn1_identifier.c
+ ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Determine the length required when encoding the ASN.1 Identifier
+ @param id The ASN.1 identifier to encode
+ @param idlen [out] The required length to encode list
+ @return CRYPT_OK if successful
+*/
+
+int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen)
+{
+ return der_encode_asn1_identifier(id, NULL, idlen);
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_length_asn1_length.c b/src/ltc/pk/asn1/der/general/der_length_asn1_length.c
new file mode 100644
index 00000000..1271e1cb
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_length_asn1_length.c
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_asn1_length.c
+ ASN.1 DER, determine the length of the ASN.1 length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Determine the length required to encode len in the ASN.1 length field
+ @param len The length to encode
+ @param outlen [out] The length that's required to store len
+ @return CRYPT_OK if successful
+*/
+int der_length_asn1_length(unsigned long len, unsigned long *outlen)
+{
+ return der_encode_asn1_length(len, NULL, outlen);
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c b/src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c
index c3472519..15e90f88 100644
--- a/src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c
+++ b/src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c
@@ -28,7 +28,7 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
- int t;
+ int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -45,23 +45,12 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* is it too long? */
if (len > *outlen) {
@@ -69,7 +58,7 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c b/src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c
index 18b926ea..fee1c703 100644
--- a/src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c
+++ b/src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c
@@ -47,23 +47,11 @@ int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x16;
- if (inlen < 128) {
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else if (inlen < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((inlen>>16)&255);
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else {
- return CRYPT_INVALID_ARG;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store octets */
for (y = 0; y < inlen; y++) {
diff --git a/src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c b/src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c
index 5f1a78d1..422c4d33 100644
--- a/src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c
+++ b/src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c
@@ -154,6 +154,7 @@ int der_ia5_value_decode(int v)
int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
+ int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@@ -165,21 +166,10 @@ int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, un
}
}
- if (noctets < 128) {
- /* 16 LL DD DD DD ... */
- *outlen = 2 + noctets;
- } else if (noctets < 256) {
- /* 16 81 LL DD DD DD ... */
- *outlen = 3 + noctets;
- } else if (noctets < 65536UL) {
- /* 16 82 LL LL DD DD DD ... */
- *outlen = 4 + noctets;
- } else if (noctets < 16777216UL) {
- /* 16 83 LL LL LL DD DD DD ... */
- *outlen = 5 + noctets;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + noctets;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/integer/der_decode_integer.c b/src/ltc/pk/asn1/der/integer/der_decode_integer.c
index 88cf93f3..e5c5c122 100644
--- a/src/ltc/pk/asn1/der/integer/der_decode_integer.c
+++ b/src/ltc/pk/asn1/der/integer/der_decode_integer.c
@@ -25,7 +25,7 @@
*/
int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
{
- unsigned long x, y, z;
+ unsigned long x, y;
int err;
LTC_ARGCHK(num != NULL);
@@ -42,45 +42,15 @@ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
return CRYPT_INVALID_PACKET;
}
- /* now decode the len stuff */
- z = in[x++];
-
- if ((z & 0x80) == 0x00) {
- /* short form */
-
- /* will it overflow? */
- if (x + z > inlen) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* no so read it */
- if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
- return err;
- }
- } else {
- /* long form */
- z &= 0x7F;
-
- /* will number of length bytes overflow? (or > 4) */
- if (((x + z) > inlen) || (z > 4) || (z == 0)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* now read it in */
- y = 0;
- while (z--) {
- y = ((unsigned long)(in[x++])) | (y << 8);
- }
-
- /* now will reading y bytes overrun? */
- if ((x + y) > inlen) {
- return CRYPT_INVALID_PACKET;
- }
+ /* get the length of the data */
+ inlen -= x;
+ if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) {
+ return err;
+ }
+ x += inlen;
- /* no so read it */
- if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
- return err;
- }
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
+ return err;
}
/* see if it's negative */
diff --git a/src/ltc/pk/asn1/der/integer/der_encode_integer.c b/src/ltc/pk/asn1/der/integer/der_encode_integer.c
index a8bada55..3bd95932 100644
--- a/src/ltc/pk/asn1/der/integer/der_encode_integer.c
+++ b/src/ltc/pk/asn1/der/integer/der_encode_integer.c
@@ -26,7 +26,7 @@
*/
int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
{
- unsigned long tmplen, y;
+ unsigned long tmplen, y, len;
int err, leading_zero;
LTC_ARGCHK(num != NULL);
@@ -63,24 +63,11 @@ int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
/* now store initial data */
*out++ = 0x02;
- if (y < 128) {
- /* short form */
- *out++ = (unsigned char)y;
- } else if (y < 256) {
- *out++ = 0x81;
- *out++ = (unsigned char)y;
- } else if (y < 65536UL) {
- *out++ = 0x82;
- *out++ = (unsigned char)((y>>8)&255);
- *out++ = (unsigned char)y;
- } else if (y < 16777216UL) {
- *out++ = 0x83;
- *out++ = (unsigned char)((y>>16)&255);
- *out++ = (unsigned char)((y>>8)&255);
- *out++ = (unsigned char)y;
- } else {
- return CRYPT_INVALID_ARG;
+ len = *outlen - 1;
+ if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) {
+ return err;
}
+ out += len;
/* now store msbyte of zero if num is non-zero */
if (leading_zero) {
diff --git a/src/ltc/pk/asn1/der/integer/der_length_integer.c b/src/ltc/pk/asn1/der/integer/der_length_integer.c
index 753ef0e0..60daffa7 100644
--- a/src/ltc/pk/asn1/der/integer/der_length_integer.c
+++ b/src/ltc/pk/asn1/der/integer/der_length_integer.c
@@ -24,7 +24,7 @@
int der_length_integer(void *num, unsigned long *outlen)
{
unsigned long z, len;
- int leading_zero;
+ int leading_zero, err;
LTC_ARGCHK(num != NULL);
LTC_ARGCHK(outlen != NULL);
@@ -40,35 +40,21 @@ int der_length_integer(void *num, unsigned long *outlen)
}
/* size for bignum */
- z = len = leading_zero + mp_unsigned_bin_size(num);
+ len = leading_zero + mp_unsigned_bin_size(num);
} else {
/* it's negative */
/* find power of 2 that is a multiple of eight and greater than count bits */
z = mp_count_bits(num);
z = z + (8 - (z & 7));
if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z;
- len = z = z >> 3;
+ len = z >> 3;
}
- /* now we need a length */
- if (z < 128) {
- /* short form */
- ++len;
- } else {
- /* long form (relies on z != 0), assumes length bytes < 128 */
- ++len;
-
- while (z) {
- ++len;
- z >>= 8;
- }
+ if ((err = der_length_asn1_length(len, &z)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + z + len;
- /* we need a 0x02 to indicate it's INTEGER */
- ++len;
-
- /* return length */
- *outlen = len;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c
index c957565d..48a95473 100644
--- a/src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c
+++ b/src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c
@@ -26,6 +26,7 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
unsigned long *words, unsigned long *outlen)
{
unsigned long x, y, t, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(words != NULL);
@@ -38,6 +39,7 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
/* must be room for at least two words */
if (*outlen < 2) {
+ *outlen = 2;
return CRYPT_BUFFER_OVERFLOW;
}
@@ -47,21 +49,14 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
return CRYPT_INVALID_PACKET;
}
- /* get the length */
- if (in[x] < 128) {
- len = in[x++];
- } else {
- if (in[x] < 0x81 || in[x] > 0x82) {
- return CRYPT_INVALID_PACKET;
- }
- y = in[x++] & 0x7F;
- len = 0;
- while (y--) {
- len = (len << 8) | (unsigned long)in[x++];
- }
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
- if (len < 1 || (len + x) > inlen) {
+ if ((len == 0) || (len > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}
@@ -73,21 +68,28 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
if (!(in[x++] & 0x80)) {
/* store t */
if (y >= *outlen) {
- return CRYPT_BUFFER_OVERFLOW;
- }
- if (y == 0) {
- words[0] = t / 40;
- words[1] = t % 40;
- y = 2;
+ y++;
} else {
- words[y++] = t;
+ if (y == 0) {
+ words[0] = t / 40;
+ words[1] = t % 40;
+ y = 2;
+ } else {
+ words[y++] = t;
+ }
}
- t = 0;
+ t = 0;
}
}
+ if (y > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ err = CRYPT_OK;
+ }
+
*outlen = y;
- return CRYPT_OK;
+ return err;
}
#endif
diff --git a/src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c
index b1ce62c9..4b397b64 100644
--- a/src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c
+++ b/src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c
@@ -55,18 +55,11 @@ int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
/* store header + length */
x = 0;
out[x++] = 0x06;
- if (z < 128) {
- out[x++] = (unsigned char)z;
- } else if (z < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)z;
- } else if (z < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((z>>8)&255);
- out[x++] = (unsigned char)(z&255);
- } else {
- return CRYPT_INVALID_ARG;
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* store first byte */
wordbuf = words[0] * 40 + words[1];
diff --git a/src/ltc/pk/asn1/der/octet/der_decode_octet_string.c b/src/ltc/pk/asn1/der/octet/der_decode_octet_string.c
index 02859dca..a9b3cdc5 100644
--- a/src/ltc/pk/asn1/der/octet/der_decode_octet_string.c
+++ b/src/ltc/pk/asn1/der/octet/der_decode_octet_string.c
@@ -28,6 +28,7 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -44,23 +45,12 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* is it too long? */
if (len > *outlen) {
@@ -68,7 +58,7 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/octet/der_encode_octet_string.c b/src/ltc/pk/asn1/der/octet/der_encode_octet_string.c
index 9c9d1a65..fd79c673 100644
--- a/src/ltc/pk/asn1/der/octet/der_encode_octet_string.c
+++ b/src/ltc/pk/asn1/der/octet/der_encode_octet_string.c
@@ -48,23 +48,11 @@ int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x04;
- if (inlen < 128) {
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else if (inlen < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((inlen>>16)&255);
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else {
- return CRYPT_INVALID_ARG;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store octets */
for (y = 0; y < inlen; y++) {
diff --git a/src/ltc/pk/asn1/der/octet/der_length_octet_string.c b/src/ltc/pk/asn1/der/octet/der_length_octet_string.c
index 10c9e892..9e5386a3 100644
--- a/src/ltc/pk/asn1/der/octet/der_length_octet_string.c
+++ b/src/ltc/pk/asn1/der/octet/der_length_octet_string.c
@@ -22,23 +22,15 @@
*/
int der_length_octet_string(unsigned long noctets, unsigned long *outlen)
{
+ unsigned long x;
+ int err;
+
LTC_ARGCHK(outlen != NULL);
- if (noctets < 128) {
- /* 04 LL DD DD DD ... */
- *outlen = 2 + noctets;
- } else if (noctets < 256) {
- /* 04 81 LL DD DD DD ... */
- *outlen = 3 + noctets;
- } else if (noctets < 65536UL) {
- /* 04 82 LL LL DD DD DD ... */
- *outlen = 4 + noctets;
- } else if (noctets < 16777216UL) {
- /* 04 83 LL LL LL DD DD DD ... */
- *outlen = 5 + noctets;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + noctets;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c b/src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c
index 69474292..1ec9e3c7 100644
--- a/src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c
+++ b/src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c
@@ -28,7 +28,7 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
- int t;
+ int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -45,23 +45,12 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* is it too long? */
if (len > *outlen) {
@@ -69,7 +58,7 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c b/src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c
index ee54e48f..bd593916 100644
--- a/src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c
+++ b/src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c
@@ -47,23 +47,11 @@ int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x13;
- if (inlen < 128) {
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else if (inlen < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((inlen>>16)&255);
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else {
- return CRYPT_INVALID_ARG;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store octets */
for (y = 0; y < inlen; y++) {
diff --git a/src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c b/src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c
index 40f0beb4..b6eb8502 100644
--- a/src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c
+++ b/src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c
@@ -126,6 +126,7 @@ int der_printable_value_decode(int v)
int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
+ int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@@ -137,21 +138,10 @@ int der_length_printable_string(const unsigned char *octets, unsigned long nocte
}
}
- if (noctets < 128) {
- /* 16 LL DD DD DD ... */
- *outlen = 2 + noctets;
- } else if (noctets < 256) {
- /* 16 81 LL DD DD DD ... */
- *outlen = 3 + noctets;
- } else if (noctets < 65536UL) {
- /* 16 82 LL LL DD DD DD ... */
- *outlen = 4 + noctets;
- } else if (noctets < 16777216UL) {
- /* 16 83 LL LL LL DD DD DD ... */
- *outlen = 5 + noctets;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + noctets;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c
index b1473819..10cfd218 100644
--- a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c
+++ b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c
@@ -22,317 +22,13 @@
@param inlen The size of the input
@param list The list of items to decode
@param outlen The number of items in the list
- @param ordered Search an unordeded or ordered list
+ @param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
- ltc_asn1_list *list, unsigned long outlen, int ordered)
+ ltc_asn1_list *list, unsigned long outlen, unsigned int flags)
{
- int err, i;
- ltc_asn1_type type;
- unsigned long size, x, y, z, blksize;
- void *data;
-
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(list != NULL);
-
- /* get blk size */
- if (inlen < 2) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
- x = 0;
- if (in[x] != 0x30 && in[x] != 0x31) {
- return CRYPT_INVALID_PACKET;
- }
- ++x;
-
- /* check if the msb is set, which signals that the
- * 7 lsb bits represent the number of bytes of the length
- */
- if (in[x] < 128) {
- blksize = in[x++];
- } else {
- if (in[x] < 0x81 || in[x] > 0x83) {
- return CRYPT_INVALID_PACKET;
- }
- y = in[x++] & 0x7F;
-
- /* would reading the len bytes overrun? */
- if (x + y > inlen) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read len */
- blksize = 0;
- while (y--) {
- blksize = (blksize << 8) | (unsigned long)in[x++];
- }
- }
-
- /* would this blksize overflow? */
- if (x + blksize > inlen) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* mark all as unused */
- for (i = 0; i < (int)outlen; i++) {
- list[i].used = 0;
- }
-
- /* ok read data */
- inlen = blksize;
- for (i = 0; i < (int)outlen; i++) {
- z = 0;
- type = list[i].type;
- size = list[i].size;
- data = list[i].data;
- if (!ordered && list[i].used == 1) { continue; }
-
- if (type == LTC_ASN1_EOL) {
- break;
- }
-
- /* handle context specific tags - just skip the tag + len bytes */
- z = 0;
- if (list[i].tag > 0 && list[i].tag == in[x + z++]) {
- if (in[x+z] & 0x80) {
- y = in[x + z++] & 0x7F;
- if (y == 0 || y > 2) { return CRYPT_INVALID_PACKET; }
- z += y;
- } else {
- z++;
- }
- x += z;
- inlen -= z;
- }
-
- switch (type) {
- case LTC_ASN1_BOOLEAN:
- z = inlen;
- if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_boolean(&z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_INTEGER:
- z = inlen;
- if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_SHORT_INTEGER:
- z = inlen;
- if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
-
- break;
-
- case LTC_ASN1_BIT_STRING:
- z = inlen;
- if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_RAW_BIT_STRING:
- z = inlen;
- if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_OCTET_STRING:
- z = inlen;
- if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_NULL:
- if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
- if (!ordered || list[i].optional) { continue; }
- err = CRYPT_INVALID_PACKET;
- goto LBL_ERR;
- }
- z = 2;
- break;
-
- case LTC_ASN1_OBJECT_IDENTIFIER:
- z = inlen;
- if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_TELETEX_STRING:
- z = inlen;
- if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_IA5_STRING:
- z = inlen;
- if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
-
- case LTC_ASN1_PRINTABLE_STRING:
- z = inlen;
- if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_UTF8_STRING:
- z = inlen;
- if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_UTCTIME:
- z = inlen;
- if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_GENERALIZEDTIME:
- z = inlen;
- if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
- if (!ordered) { continue; }
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_SET:
- z = inlen;
- if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_SETOF:
- case LTC_ASN1_SEQUENCE:
- /* detect if we have the right type */
- if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
- err = CRYPT_INVALID_PACKET;
- goto LBL_ERR;
- }
-
- z = inlen;
- if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
-
- case LTC_ASN1_CHOICE:
- z = inlen;
- if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
- case LTC_ASN1_EOL:
- err = CRYPT_INVALID_ARG;
- goto LBL_ERR;
- }
- x += z;
- inlen -= z;
- list[i].used = 1;
- if (!ordered) {
- /* restart the decoder */
- i = -1;
- }
- }
-
- for (i = 0; i < (int)outlen; i++) {
- if (list[i].used == 0 && list[i].optional == 0) {
- err = CRYPT_INVALID_PACKET;
- goto LBL_ERR;
- }
- }
-
- if (inlen == 0) {
- err = CRYPT_OK;
- } else {
- err = CRYPT_INPUT_TOO_LONG;
- }
-
-LBL_ERR:
- return err;
+ return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags);
}
#endif
diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c
index 142ef95a..44c9c478 100644
--- a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c
+++ b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c
@@ -15,42 +15,6 @@
#ifdef LTC_DER
-static unsigned long _fetch_length(const unsigned char *in, unsigned long inlen, unsigned long *data_offset)
-{
- unsigned long x, z;
-
- *data_offset = 0;
-
- /* skip type and read len */
- if (inlen < 2) {
- return 0xFFFFFFFF;
- }
- ++in; ++(*data_offset);
-
- /* read len */
- x = *in++; ++(*data_offset);
-
- /* <128 means literal */
- if (x < 128) {
- return x+*data_offset;
- }
- x &= 0x7F; /* the lower 7 bits are the length of the length */
- inlen -= 2;
-
- /* len means len of len! */
- if (x == 0 || x > 4 || x > inlen) {
- return 0xFFFFFFFF;
- }
-
- *data_offset += x;
- z = 0;
- while (x--) {
- z = (z<<8) | ((unsigned long)*in);
- ++in;
- }
- return z+*data_offset;
-}
-
static int _new_element(ltc_asn1_list **l)
{
/* alloc new link */
@@ -80,7 +44,7 @@ static int _new_element(ltc_asn1_list **l)
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
{
ltc_asn1_list *l;
- unsigned long err, type, len, totlen, data_offset;
+ unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
void *realloc_tmp;
LTC_ARGCHK(in != NULL);
@@ -99,38 +63,77 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
/* scan the input and and get lengths and what not */
while (*inlen) {
- /* read the type byte */
- type = *in;
-
- /* fetch length */
- len = _fetch_length(in, *inlen, &data_offset);
- if (len > *inlen) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
-
/* alloc new link */
if ((err = _new_element(&l)) != CRYPT_OK) {
goto error;
}
- if ((type & 0x20) && (type != 0x30) && (type != 0x31)) {
- /* constructed, use the 'used' field to store the original identifier */
- l->used = type;
- /* treat constructed elements like SETs */
- type = 0x20;
+ id_len = *inlen;
+ if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) {
+ goto error;
}
- else if ((type & 0xC0) == 0x80) {
- /* context-specific, use the 'used' field to store the original identifier */
- l->used = type;
- /* context-specific elements are treated as opaque data */
- type = 0x80;
+ /* read the type byte */
+ identifier = *in;
+
+ if (l->type != LTC_ASN1_EOL) {
+ /* fetch length */
+ len_len = *inlen - id_len;
+#if defined(LTC_TEST_DBG)
+ data_offset = 666;
+ len = 0;
+#endif
+ if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) {
+#if defined(LTC_TEST_DBG)
+ fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
+#endif
+ goto error;
+ } else if (len > (*inlen - id_len - len_len)) {
+ err = CRYPT_INVALID_PACKET;
+#if defined(LTC_TEST_DBG)
+ fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
+#endif
+ goto error;
+ }
+ data_offset = id_len + len_len;
+#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
+ if (l->type == LTC_ASN1_CUSTOM_TYPE && l->class == LTC_ASN1_CL_CONTEXT_SPECIFIC) {
+ fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag);
+ } else {
+ fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]);
+ }
+#endif
+ len += data_offset;
+
+ if (l->type == LTC_ASN1_CUSTOM_TYPE) {
+ /* Custom type, use the 'used' field to store the original identifier */
+ l->used = identifier;
+ if (l->pc == LTC_ASN1_PC_CONSTRUCTED) {
+ /* treat constructed elements like SEQUENCEs */
+ identifier = 0x20;
+ } else {
+ /* primitive elements are treated as opaque data */
+ identifier = 0x80;
+ }
+ }
+ } else {
+ /* Init this so gcc won't complain,
+ * as this case will only be hit when we
+ * can't decode the identifier so the
+ * switch-case should go to default anyway...
+ */
+ data_offset = 0;
+ len = 0;
}
/* now switch on type */
- switch (type) {
+ switch (identifier) {
case 0x01: /* BOOLEAN */
- l->type = LTC_ASN1_BOOLEAN;
+ if (l->type != LTC_ASN1_BOOLEAN) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
l->size = 1;
l->data = XCALLOC(1, sizeof(int));
@@ -144,8 +147,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x02: /* INTEGER */
+ if (l->type != LTC_ASN1_INTEGER) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
/* init field */
- l->type = LTC_ASN1_INTEGER;
l->size = 1;
if ((err = mp_init(&l->data)) != CRYPT_OK) {
goto error;
@@ -163,8 +170,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x03: /* BIT */
+ if (l->type != LTC_ASN1_BIT_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
/* init field */
- l->type = LTC_ASN1_BIT_STRING;
l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -182,9 +193,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x04: /* OCTET */
+ if (l->type != LTC_ASN1_OCTET_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_OCTET_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -202,6 +216,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x05: /* NULL */
+ if (l->type != LTC_ASN1_NULL) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* valid NULL is 0x05 0x00 */
if (in[0] != 0x05 || in[1] != 0x00) {
@@ -210,7 +228,6 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
}
/* simple to store ;-) */
- l->type = LTC_ASN1_NULL;
l->data = NULL;
l->size = 0;
len = 2;
@@ -218,9 +235,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x06: /* OID */
+ if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_OBJECT_IDENTIFIER;
l->size = len;
if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
@@ -247,7 +267,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
case 0x0C: /* UTF8 */
/* init field */
- l->type = LTC_ASN1_UTF8_STRING;
+ if (l->type != LTC_ASN1_UTF8_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
l->size = len;
if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
@@ -265,9 +288,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x13: /* PRINTABLE */
+ if (l->type != LTC_ASN1_PRINTABLE_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_PRINTABLE_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -285,9 +311,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x14: /* TELETEXT */
+ if (l->type != LTC_ASN1_TELETEX_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_TELETEX_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -305,9 +334,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x16: /* IA5 */
+ if (l->type != LTC_ASN1_IA5_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_IA5_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -325,9 +357,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x17: /* UTC TIME */
+ if (l->type != LTC_ASN1_UTCTIME) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_UTCTIME;
l->size = 1;
if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
@@ -346,7 +381,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x18:
- l->type = LTC_ASN1_GENERALIZEDTIME;
+ if (l->type != LTC_ASN1_GENERALIZEDTIME) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
l->size = len;
if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
@@ -369,14 +409,23 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
case 0x31: /* SET */
/* init field */
- if (type == 0x20) {
- l->type = LTC_ASN1_CONSTRUCTED;
+ if (identifier == 0x20) {
+ if (l->type != LTC_ASN1_CUSTOM_TYPE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
}
- else if (type == 0x30) {
- l->type = LTC_ASN1_SEQUENCE;
+ else if (identifier == 0x30) {
+ if (l->type != LTC_ASN1_SEQUENCE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
}
else {
- l->type = LTC_ASN1_SET;
+ if (l->type != LTC_ASN1_SET) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
}
if ((l->data = XMALLOC(len)) == NULL) {
@@ -391,12 +440,19 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
/* jump to the start of the data */
in += data_offset;
*inlen -= data_offset;
- len = len - data_offset;
+ len -= data_offset;
+
+ /* save the decoded ASN.1 len */
+ len_len = len;
/* Sequence elements go as child */
if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
goto error;
}
+ if (len_len != len) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* len update */
totlen += data_offset;
@@ -410,7 +466,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x80: /* Context-specific */
- l->type = LTC_ASN1_CONTEXT_SPECIFIC;
+ if (l->type != LTC_ASN1_CUSTOM_TYPE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
err = CRYPT_MEM;
diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c
index 1361b761..280d7cdb 100644
--- a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c
+++ b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c
@@ -21,27 +21,27 @@
Decode a SEQUENCE type using a VA list
@param in Input buffer
@param inlen Length of input in octets
- @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @param a1 Initialized argument list #1
+ @param a2 Initialized argument list #2 (copy of #1)
+ @param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
-int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+static int _der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags)
{
int err;
ltc_asn1_type type;
unsigned long size, x;
void *data;
- va_list args;
ltc_asn1_list *list;
LTC_ARGCHK(in != NULL);
/* get size of output that will be required */
- va_start(args, inlen);
x = 0;
for (;;) {
- type = (ltc_asn1_type)va_arg(args, int);
- size = va_arg(args, unsigned long);
- data = va_arg(args, void*);
+ type = (ltc_asn1_type)va_arg(a1, int);
+ size = va_arg(a1, unsigned long);
+ data = va_arg(a1, void*);
LTC_UNUSED_PARAM(size);
LTC_UNUSED_PARAM(data);
@@ -72,13 +72,10 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
break;
case LTC_ASN1_EOL:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
- va_end(args);
+ case LTC_ASN1_CUSTOM_TYPE:
return CRYPT_INVALID_ARG;
}
}
- va_end(args);
/* allocate structure for x elements */
if (x == 0) {
@@ -91,12 +88,11 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
}
/* fill in the structure */
- va_start(args, inlen);
x = 0;
for (;;) {
- type = (ltc_asn1_type)va_arg(args, int);
- size = va_arg(args, unsigned long);
- data = va_arg(args, void*);
+ type = (ltc_asn1_type)va_arg(a2, int);
+ size = va_arg(a2, unsigned long);
+ data = va_arg(a2, void*);
if (type == LTC_ASN1_EOL) {
break;
@@ -125,18 +121,67 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
break;
/* coverity[dead_error_line] */
case LTC_ASN1_EOL:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
+ case LTC_ASN1_CUSTOM_TYPE:
break;
}
}
- va_end(args);
- err = der_decode_sequence(in, inlen, list, x);
+ err = der_decode_sequence_ex(in, inlen, list, x, flags);
XFREE(list);
return err;
}
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+{
+ va_list a1, a2;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+
+ va_start(a1, inlen);
+ va_start(a2, inlen);
+
+ err = _der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED);
+
+ va_end(a2);
+ va_end(a1);
+
+ return err;
+}
+
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @param flags c.f. enum ltc_der_seq
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...)
+{
+ va_list a1, a2;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+
+ va_start(a1, flags);
+ va_start(a2, flags);
+
+ err = _der_decode_sequence_va(in, inlen, a1, a2, flags);
+
+ va_end(a2);
+ va_end(a1);
+
+ return err;
+}
+
#endif
diff --git a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c
index d8ad196c..1a5d9681 100644
--- a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c
+++ b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c
@@ -31,7 +31,6 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
int err;
ltc_asn1_type type;
unsigned long size, x, y, z, i;
- unsigned char tmptag[6];
void *data;
LTC_ARGCHK(list != NULL);
@@ -53,21 +52,11 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
x = 0;
out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
- if (z < 128) {
- out[x++] = (unsigned char)z;
- } else if (z < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)z;
- } else if (z < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((z>>8UL)&255);
- out[x++] = (unsigned char)(z&255);
- } else if (z < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((z>>16UL)&255);
- out[x++] = (unsigned char)((z>>8UL)&255);
- out[x++] = (unsigned char)(z&255);
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
+ goto LBL_ERR;
}
+ x += y;
/* store data */
*outlen -= x;
@@ -192,43 +181,20 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
}
break;
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = *outlen;
+ if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
- if (list[i].tag > 0) {
- tmptag[0] = list[i].tag;
- y = 0;
- if (z < 128) {
- tmptag[1] = (unsigned char)z;
- y = 2;
- } else if (z < 256) {
- tmptag[1] = 0x81;
- tmptag[2] = (unsigned char)z;
- y = 3;
- } else if (z < 65536UL) {
- tmptag[1] = 0x82;
- tmptag[2] = (unsigned char)((z>>8UL)&255);
- tmptag[3] = (unsigned char)(z&255);
- y = 4;
- } else if (z < 16777216UL) {
- tmptag[1] = 0x83;
- tmptag[2] = (unsigned char)((z>>16UL)&255);
- tmptag[3] = (unsigned char)((z>>8UL)&255);
- tmptag[4] = (unsigned char)(z&255);
- y = 5;
- }
- XMEMMOVE(out + x + y, out + x, z);
- XMEMCPY(out + x, tmptag, y);
-
- z += y;
- }
-
x += z;
*outlen -= z;
}
diff --git a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c
index c1b40c77..c8ec59a9 100644
--- a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c
+++ b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c
@@ -71,8 +71,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
break;
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
+ case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
@@ -124,8 +123,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
break;
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
+ case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
diff --git a/src/ltc/pk/asn1/der/sequence/der_length_sequence.c b/src/ltc/pk/asn1/der/sequence/der_length_sequence.c
index 7908c5b3..a80f96b0 100644
--- a/src/ltc/pk/asn1/der/sequence/der_length_sequence.c
+++ b/src/ltc/pk/asn1/der/sequence/der_length_sequence.c
@@ -33,7 +33,7 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
{
int err;
ltc_asn1_type type;
- unsigned long size, x, y, i, z;
+ unsigned long size, x, y, i;
void *data;
LTC_ARGCHK(list != NULL);
@@ -143,6 +143,13 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
y += x;
break;
+ case LTC_ASN1_CUSTOM_TYPE:
+ if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_SEQUENCE:
@@ -152,53 +159,23 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
y += x;
break;
-
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_EOL:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
-
- /* handle context specific tags size */
- if (list[i].tag > 0) {
- if (x < 128) {
- y += 2;
- } else if (x < 256) {
- y += 3;
- } else if (x < 65536UL) {
- y += 4;
- } else if (x < 16777216UL) {
- y += 5;
- } else {
- err = CRYPT_INVALID_ARG;
- goto LBL_ERR;
- }
- }
}
- /* calc header size */
- z = y;
- if (y < 128) {
- y += 2;
- } else if (y < 256) {
- /* 0x30 0x81 LL */
- y += 3;
- } else if (y < 65536UL) {
- /* 0x30 0x82 LL LL */
- y += 4;
- } else if (y < 16777216UL) {
- /* 0x30 0x83 LL LL LL */
- y += 5;
- } else {
- err = CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
+ if (payloadlen != NULL) {
+ *payloadlen = y;
+ }
+
/* store size */
- if (payloadlen) *payloadlen = z;
- *outlen = y;
+ *outlen = y + x + 1;
err = CRYPT_OK;
LBL_ERR:
diff --git a/src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c b/src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c
index 9b9e036a..fdfe91bb 100644
--- a/src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c
+++ b/src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c
@@ -32,7 +32,7 @@ void der_sequence_shrink(ltc_asn1_list *in)
}
switch (in->type) {
- case LTC_ASN1_CONSTRUCTED:
+ case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_SET:
case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break;
default: break;
diff --git a/src/ltc/pk/asn1/der/set/der_encode_set.c b/src/ltc/pk/asn1/der/set/der_encode_set.c
index fef3092b..a3485f2d 100644
--- a/src/ltc/pk/asn1/der/set/der_encode_set.c
+++ b/src/ltc/pk/asn1/der/set/der_encode_set.c
@@ -18,30 +18,7 @@
/* LTC define to ASN.1 TAG */
static int _ltc_to_asn1(ltc_asn1_type v)
{
- switch (v) {
- case LTC_ASN1_BOOLEAN: return 0x01;
- case LTC_ASN1_INTEGER:
- case LTC_ASN1_SHORT_INTEGER: return 0x02;
- case LTC_ASN1_RAW_BIT_STRING:
- case LTC_ASN1_BIT_STRING: return 0x03;
- case LTC_ASN1_OCTET_STRING: return 0x04;
- case LTC_ASN1_NULL: return 0x05;
- case LTC_ASN1_OBJECT_IDENTIFIER: return 0x06;
- case LTC_ASN1_UTF8_STRING: return 0x0C;
- case LTC_ASN1_PRINTABLE_STRING: return 0x13;
- case LTC_ASN1_TELETEX_STRING: return 0x14;
- case LTC_ASN1_IA5_STRING: return 0x16;
- case LTC_ASN1_UTCTIME: return 0x17;
- case LTC_ASN1_GENERALIZEDTIME: return 0x18;
- case LTC_ASN1_SEQUENCE: return 0x30;
- case LTC_ASN1_SET:
- case LTC_ASN1_SETOF: return 0x31;
- case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
- case LTC_ASN1_EOL: return -1;
- }
- return -1;
+ return der_asn1_type_to_identifier_map[v];
}
diff --git a/src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c b/src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c
index 52d0e1ae..8c1de289 100644
--- a/src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c
+++ b/src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c
@@ -23,7 +23,8 @@
*/
int der_length_short_integer(unsigned long num, unsigned long *outlen)
{
- unsigned long z, y, len;
+ unsigned long z, y;
+ int err;
LTC_ARGCHK(outlen != NULL);
@@ -41,22 +42,15 @@ int der_length_short_integer(unsigned long num, unsigned long *outlen)
/* handle zero */
if (z == 0) {
z = 1;
+ } else if ((num&(1UL<<((z<<3) - 1))) != 0) {
+ /* in case msb is set */
+ ++z;
}
- /* we need a 0x02 to indicate it's INTEGER */
- len = 1;
-
- /* length byte */
- ++len;
-
- /* bytes in value */
- len += z;
-
- /* see if msb is set */
- len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
-
- /* return length */
- *outlen = len;
+ if ((err = der_length_asn1_length(z, &y)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + y + z;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c b/src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c
index 0c7c3c8f..cd530a2b 100644
--- a/src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c
+++ b/src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c
@@ -27,7 +27,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
- int t;
+ int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -44,23 +44,12 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* is it too long? */
if (len > *outlen) {
@@ -68,7 +57,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c b/src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c
index 29fe5b0b..a35c6d76 100644
--- a/src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c
+++ b/src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c
@@ -170,6 +170,7 @@ int der_teletex_value_decode(int v)
int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
+ int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@@ -181,21 +182,10 @@ int der_length_teletex_string(const unsigned char *octets, unsigned long noctets
}
}
- if (noctets < 128) {
- /* 16 LL DD DD DD ... */
- *outlen = 2 + noctets;
- } else if (noctets < 256) {
- /* 16 81 LL DD DD DD ... */
- *outlen = 3 + noctets;
- } else if (noctets < 65536UL) {
- /* 16 82 LL LL DD DD DD ... */
- *outlen = 4 + noctets;
- } else if (noctets < 16777216UL) {
- /* 16 83 LL LL LL DD DD DD ... */
- *outlen = 5 + noctets;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + noctets;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c b/src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c
index d857ce95..c86d6603 100644
--- a/src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c
+++ b/src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c
@@ -29,6 +29,7 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
{
wchar_t tmp;
unsigned long x, y, z, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -45,25 +46,14 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
@@ -91,15 +81,19 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);
}
- if (y > *outlen) {
- *outlen = y;
- return CRYPT_BUFFER_OVERFLOW;
+ if (y < *outlen) {
+ out[y] = tmp;
}
- out[y++] = tmp;
+ y++;
+ }
+ if (y > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ err = CRYPT_OK;
}
*outlen = y;
- return CRYPT_OK;
+ return err;
}
#endif
diff --git a/src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c b/src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c
index 63ad840f..1c6e09b5 100644
--- a/src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c
+++ b/src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c
@@ -28,6 +28,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -38,46 +39,26 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG;
len += der_utf8_charsize(in[x]);
}
-
- if (len < 128) {
- y = 2 + len;
- } else if (len < 256) {
- y = 3 + len;
- } else if (len < 65536UL) {
- y = 4 + len;
- } else if (len < 16777216UL) {
- y = 5 + len;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
+ return err;
}
+ x += len + 1;
/* too big? */
- if (y > *outlen) {
- *outlen = len;
+ if (x > *outlen) {
+ *outlen = x;
return CRYPT_BUFFER_OVERFLOW;
}
/* encode the header+len */
x = 0;
out[x++] = 0x0C;
- if (len < 128) {
- out[x++] = (unsigned char)len;
- } else if (len < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)len;
- } else if (len < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((len>>8)&255);
- out[x++] = (unsigned char)(len&255);
- } else if (len < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((len>>16)&255);
- out[x++] = (unsigned char)((len>>8)&255);
- out[x++] = (unsigned char)(len&255);
- } else {
- /* coverity[dead_error_line] */
- return CRYPT_INVALID_ARG;
+
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* store UTF8 */
for (y = 0; y < inlen; y++) {
@@ -91,7 +72,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
}
}
- /* retun length */
+ /* return length */
*outlen = x;
return CRYPT_OK;
diff --git a/src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c b/src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c
index 88f4355e..b4292846 100644
--- a/src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c
+++ b/src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c
@@ -65,6 +65,7 @@ int der_utf8_valid_char(const wchar_t c)
int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen)
{
unsigned long x, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(outlen != NULL);
@@ -75,21 +76,10 @@ int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned lo
len += der_utf8_charsize(in[x]);
}
- if (len < 128) {
- /* 0C LL DD DD DD ... */
- *outlen = 2 + len;
- } else if (len < 256) {
- /* 0C 81 LL DD DD DD ... */
- *outlen = 3 + len;
- } else if (len < 65536UL) {
- /* 0C 82 LL LL DD DD DD ... */
- *outlen = 4 + len;
- } else if (len < 16777216UL) {
- /* 0C 83 LL LL LL DD DD DD ... */
- *outlen = 5 + len;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + len;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.c b/src/ltc/pk/asn1/x509/x509_decode_subject_public_key_info.c
index 51bf37c5..c68b4a3b 100644
--- a/src/ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.c
+++ b/src/ltc/pk/asn1/x509/x509_decode_subject_public_key_info.c
@@ -7,9 +7,10 @@
* guarantee it works.
*/
#include "tomcrypt.h"
+
/**
- @file der_decode_subject_public_key_info.c
- ASN.1 DER, encode a Subject Public Key structure --nmav
+ @file x509_decode_subject_public_key_info.c
+ ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
*/
#ifdef LTC_DER
@@ -25,7 +26,7 @@
* }
*/
/**
- Decode a subject public key info
+ Decode a SubjectPublicKeyInfo
@param in The input buffer
@param inlen The length of the input buffer
@param algorithm One out of the enum #public_key_algorithms
@@ -33,21 +34,12 @@
@param public_key_len [in/out] The length of the public key buffer and the written length
@param parameters_type The parameters' type out of the enum ltc_asn1_type
@param parameters The parameters to include
- @param parameters_len The number of parameters to include
+ @param parameters_len [in/out]The number of parameters to include
@return CRYPT_OK on success
*/
-int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
- unsigned int algorithm, void* public_key, unsigned long* public_key_len,
- unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
-{
- return der_decode_subject_public_key_info_ex(in, inlen, algorithm, public_key, public_key_len,
- parameters_type, parameters, parameters_len, NULL);
-}
-
-int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long inlen,
+int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
unsigned int algorithm, void* public_key, unsigned long* public_key_len,
- unsigned long parameters_type, void* parameters, unsigned long parameters_len,
- unsigned long *parameters_outsize)
+ unsigned long parameters_type, void* parameters, unsigned long *parameters_len)
{
int err;
unsigned long len;
@@ -60,6 +52,7 @@ int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != 0);
LTC_ARGCHK(public_key_len != NULL);
+ LTC_ARGCHK(parameters_len != NULL);
err = pk_get_oid(algorithm, &oid);
if (err != CRYPT_OK) {
@@ -75,7 +68,7 @@ int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long
/* this includes the internal hash ID and optional params (NULL in this case) */
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
- LTC_SET_ASN1(alg_id, 1, (ltc_asn1_type)parameters_type, parameters, parameters_len);
+ LTC_SET_ASN1(alg_id, 1, (ltc_asn1_type)parameters_type, parameters, *parameters_len);
/* the actual format of the SSL DER key is odd, it stores a RSAPublicKey
* in a **BIT** string ... so we have to extract it then proceed to convert bit to octet
@@ -88,7 +81,7 @@ int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long
goto LBL_ERR;
}
- if (parameters_outsize) *parameters_outsize = alg_id[1].size;
+ *parameters_len = alg_id[1].size;
if ((alg_id[0].size != oid.OIDlen) ||
XMEMCMP(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) {
diff --git a/src/ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.c b/src/ltc/pk/asn1/x509/x509_encode_subject_public_key_info.c
index dcb869a9..8148a185 100644
--- a/src/ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.c
+++ b/src/ltc/pk/asn1/x509/x509_encode_subject_public_key_info.c
@@ -9,8 +9,8 @@
#include "tomcrypt.h"
/**
- @file der_encode_subject_public_key_info.c
- ASN.1 DER, encode a Subject Public Key structure --nmav
+ @file x509_encode_subject_public_key_info.c
+ ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
*/
#ifdef LTC_DER
@@ -26,7 +26,7 @@
* }
*/
/**
- Encode a subject public key info
+ Encode a SubjectPublicKeyInfo
@param out The output buffer
@param outlen [in/out] Length of buffer and resulting length of output
@param algorithm One out of the enum #public_key_algorithms
@@ -37,7 +37,7 @@
@param parameters_len The number of parameters to include
@return CRYPT_OK on success
*/
-int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
+int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
unsigned int algorithm, void* public_key, unsigned long public_key_len,
unsigned long parameters_type, void* parameters, unsigned long parameters_len)
{
diff --git a/src/ltc/pk/dsa/dsa_export.c b/src/ltc/pk/dsa/dsa_export.c
index 1f6bb5a3..dde54583 100644
--- a/src/ltc/pk/dsa/dsa_export.c
+++ b/src/ltc/pk/dsa/dsa_export.c
@@ -86,7 +86,7 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key
LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL);
LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL);
- err = der_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp,
+ err = x509_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp,
tmplen, LTC_ASN1_SEQUENCE, int_list,
sizeof(int_list) / sizeof(int_list[0]));
diff --git a/src/ltc/pk/dsa/dsa_import.c b/src/ltc/pk/dsa/dsa_import.c
index e6a75602..5e77b1e7 100644
--- a/src/ltc/pk/dsa/dsa_import.c
+++ b/src/ltc/pk/dsa/dsa_import.c
@@ -25,7 +25,7 @@
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
{
int err, stat;
- unsigned long zero = 0;
+ unsigned long zero = 0, len;
unsigned char* tmpbuf = NULL;
unsigned char flags[1];
@@ -102,9 +102,10 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
goto LBL_ERR;
}
- err = der_decode_subject_public_key_info(in, inlen, PKA_DSA,
+ len = 3;
+ err = x509_decode_subject_public_key_info(in, inlen, PKA_DSA,
tmpbuf, &tmpbuf_len,
- LTC_ASN1_SEQUENCE, params, 3);
+ LTC_ASN1_SEQUENCE, params, &len);
if (err != CRYPT_OK) {
XFREE(tmpbuf);
goto LBL_ERR;
diff --git a/src/ltc/pk/dsa/dsa_verify_hash.c b/src/ltc/pk/dsa/dsa_verify_hash.c
index 3d3fab5f..eb642d5b 100644
--- a/src/ltc/pk/dsa/dsa_verify_hash.c
+++ b/src/ltc/pk/dsa/dsa_verify_hash.c
@@ -111,7 +111,7 @@ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL);
LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL);
- err = der_decode_sequence(sig, siglen, sig_seq, 2);
+ err = der_decode_sequence_strict(sig, siglen, sig_seq, 2);
if (err != CRYPT_OK) {
goto LBL_ERR;
}
diff --git a/src/ltc/pk/ecc/ecc.c b/src/ltc/pk/ecc/ecc.c
index 0eb55023..b90afc71 100644
--- a/src/ltc/pk/ecc/ecc.c
+++ b/src/ltc/pk/ecc/ecc.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -19,10 +16,7 @@
#ifdef LTC_MECC
-/* This array holds the curve parameters:
- * - it ***MUST*** be organized by size from smallest to largest
- * - due to curve lookup by keysize the ordering is very important
- * - be careful when adding/removing items to/from this list
+/* This array holds the curve parameters.
* Curves (prime field only) are taken from:
* - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*)
* - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*)
@@ -31,8 +25,7 @@
*/
const ltc_ecc_set_type ltc_ecc_sets[] = {
#if defined(LTC_ECC_SECP112R1) || defined(LTC_ECC112)
-{ /* this curve ***MUST*** be the first from all with size 14 (backward compatibility reasons) */
- /* size/bytes */ 14,
+{
/* curve name */ "SECP112R1",
/* prime */ "DB7C2ABF62E35E668076BEAD208B",
/* A */ "DB7C2ABF62E35E668076BEAD2088",
@@ -41,12 +34,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "09487239995A5EE76B55F9C2F098",
/* Gy */ "A89CE5AF8724C0A23E0E0FF77500",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,6}, 5 }
+ /* OID */ { 1,3,132,0,6 }, 5
},
#endif
#ifdef LTC_ECC_SECP112R2
{
- /* size/bytes */ 14,
/* curve name */ "SECP112R2",
/* prime */ "DB7C2ABF62E35E668076BEAD208B",
/* A */ "6127C24C05F38A0AAAF65C0EF02C",
@@ -55,12 +47,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "4BA30AB5E892B4E1649DD0928643",
/* Gy */ "ADCD46F5882E3747DEF36E956E97",
/* cofactor */ 4,
- /* OID struct */ { {1,3,132,0,7}, 5 }
+ /* OID */ { 1,3,132,0,7 }, 5
},
#endif
#if defined(LTC_ECC_SECP128R1) || defined(LTC_ECC128)
-{ /* this curve ***MUST*** be the first from all with size 16 (backward compatibility reasons) */
- /* size/bytes */ 16,
+{
/* curve name */ "SECP128R1",
/* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
/* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
@@ -69,12 +60,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "161FF7528B899B2D0C28607CA52C5B86",
/* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,28}, 5 }
+ /* OID */ { 1,3,132,0,28 }, 5
},
#endif
#ifdef LTC_ECC_SECP128R2
{
- /* size/bytes */ 16,
/* curve name */ "SECP128R2",
/* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
/* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1",
@@ -83,12 +73,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140",
/* Gy */ "27B6916A894D3AEE7106FE805FC34B44",
/* cofactor */ 4,
- /* OID struct */ { {1,3,132,0,29}, 5 }
+ /* OID */ { 1,3,132,0,29 }, 5
},
#endif
#if defined(LTC_ECC_SECP160R1) || defined(LTC_ECC160)
-{ /* this curve ***MUST*** be the first from all with size 20 (backward compatibility reasons) */
- /* size/bytes */ 20,
+{
/* curve name */ "SECP160R1",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
@@ -97,12 +86,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82",
/* Gy */ "23A628553168947D59DCC912042351377AC5FB32",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,8}, 5 }
+ /* OID */ { 1,3,132,0,8 }, 5
},
#endif
#ifdef LTC_ECC_SECP160R2
{
- /* size/bytes */ 20,
/* curve name */ "SECP160R2",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
@@ -111,12 +99,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D",
/* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,30}, 5 }
+ /* OID */ { 1,3,132,0,30 }, 5
},
#endif
#ifdef LTC_ECC_SECP160K1
{
- /* size/bytes */ 20,
/* curve name */ "SECP160K1",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
/* A */ "0000000000000000000000000000000000000000",
@@ -125,26 +112,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
/* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,9}, 5 }
-},
-#endif
-#ifdef LTC_ECC_BRAINPOOLP160R1
-{
- /* size/bytes */ 20,
- /* curve name */ "BRAINPOOLP160R1",
- /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
- /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
- /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58",
- /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
- /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
- /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321",
- /* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,1}, 10 }
+ /* OID */ { 1,3,132,0,9 }, 5
},
#endif
#if defined(LTC_ECC_SECP192R1) || defined(LTC_ECC192)
-{ /* this curve ***MUST*** be the first from all with size 24 (backward compatibility reasons) */
- /* size/bytes */ 24,
+{
/* curve name */ "SECP192R1", /* same as: NISTP192 PRIME192V1, old libtomcrypt name: ECC-192 */
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
@@ -153,12 +125,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
/* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,1}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,1 }, 7
},
#endif
#ifdef LTC_ECC_PRIME192V2
{
- /* size/bytes */ 24,
/* curve name */ "PRIME192V2",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
@@ -167,12 +138,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
/* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,2}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,2 }, 7
},
#endif
#ifdef LTC_ECC_PRIME192V3
{
- /* size/bytes */ 24,
/* curve name */ "PRIME192V3",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
@@ -181,12 +151,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
/* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,3}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,3 }, 7
},
#endif
#ifdef LTC_ECC_SECP192K1
{
- /* size/bytes */ 24,
/* curve name */ "SECP192K1",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
/* A */ "000000000000000000000000000000000000000000000000",
@@ -195,26 +164,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
/* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,31}, 5 }
-},
-#endif
-#ifdef LTC_ECC_BRAINPOOLP192R1
-{
- /* size/bytes */ 24,
- /* curve name */ "BRAINPOOLP192R1",
- /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
- /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
- /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
- /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
- /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
- /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
- /* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,3}, 10 }
+ /* OID */ { 1,3,132,0,31 }, 5
},
#endif
#if defined(LTC_ECC_SECP224R1) || defined(LTC_ECC224)
-{ /* this curve ***MUST*** be the first from all with size 28 (backward compatibility reasons) */
- /* size/bytes */ 28,
+{
/* curve name */ "SECP224R1", /* same as: NISTP224, old libtomcrypt name: ECC-224 */
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
@@ -223,12 +177,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
/* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,33}, 5 }
+ /* OID */ { 1,3,132,0,33 }, 5
},
#endif
#ifdef LTC_ECC_SECP224K1
{
- /* size/bytes */ 28,
/* curve name */ "SECP224K1",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
/* A */ "00000000000000000000000000000000000000000000000000000000",
@@ -237,26 +190,63 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
/* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,32}, 5 }
+ /* OID */ { 1,3,132,0,32 }, 5
},
#endif
-#ifdef LTC_ECC_BRAINPOOLP224R1
+#if defined(LTC_ECC_SECP256R1) || defined(LTC_ECC256)
{
- /* size/bytes */ 28,
- /* curve name */ "BRAINPOOLP224R1",
- /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
- /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
- /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
- /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
- /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
- /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
+ /* curve name */ "SECP256R1", /* same as: NISTP256 PRIME256V1, old libtomcrypt name: ECC-256 */
+ /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+ /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+ /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+ /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,5}, 10 }
+ /* OID */ { 1,2,840,10045,3,1,7 }, 7
+},
+#endif
+#ifdef LTC_ECC_SECP256K1
+{
+ /* curve name */ "SECP256K1",
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
+ /* A */ "0000000000000000000000000000000000000000000000000000000000000000",
+ /* B */ "0000000000000000000000000000000000000000000000000000000000000007",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
+ /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
+ /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,132,0,10 }, 5
+},
+#endif
+#if defined(LTC_ECC_SECP384R1) || defined(LTC_ECC384)
+{
+ /* curve name */ "SECP384R1", /* same as: NISTP384, old libtomcrypt name: ECC-384 */
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+ /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,132,0,34 }, 5
+},
+#endif
+#if defined(LTC_ECC_SECP521R1) || defined(LTC_ECC521)
+{
+ /* curve name */ "SECP521R1", /* same as: NISTP521, old libtomcrypt name: ECC-521 */
+ /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+ /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+ /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+ /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+ /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,132,0,35 }, 5
},
#endif
#ifdef LTC_ECC_PRIME239V1
{
- /* size/bytes */ 30,
/* curve name */ "PRIME239V1",
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
@@ -265,12 +255,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
/* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,4}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,4 }, 7
},
#endif
#ifdef LTC_ECC_PRIME239V2
{
- /* size/bytes */ 30,
/* curve name */ "PRIME239V2",
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
@@ -279,12 +268,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
/* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,5}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,5 }, 7
},
#endif
#ifdef LTC_ECC_PRIME239V3
{
- /* size/bytes */ 30,
/* curve name */ "PRIME239V3",
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
@@ -293,40 +281,50 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
/* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,6}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,6 }, 7
},
#endif
-#if defined(LTC_ECC_SECP256R1) || defined(LTC_ECC256)
-{ /* this curve ***MUST*** be the first from all with size 32 (backward compatibility reasons) */
- /* size/bytes */ 32,
- /* curve name */ "SECP256R1", /* same as: NISTP256 PRIME256V1, old libtomcrypt name: ECC-256 */
- /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
- /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
- /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
- /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
- /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
- /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+#ifdef LTC_ECC_BRAINPOOLP160R1
+{
+ /* curve name */ "BRAINPOOLP160R1",
+ /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
+ /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
+ /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58",
+ /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
+ /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
+ /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,7}, 7 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,1 }, 10
},
#endif
-#ifdef LTC_ECC_SECP256K1
+#ifdef LTC_ECC_BRAINPOOLP192R1
{
- /* size/bytes */ 32,
- /* curve name */ "SECP256K1",
- /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
- /* A */ "0000000000000000000000000000000000000000000000000000000000000000",
- /* B */ "0000000000000000000000000000000000000000000000000000000000000007",
- /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
- /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
- /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+ /* curve name */ "BRAINPOOLP192R1",
+ /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
+ /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
+ /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
+ /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
+ /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
+ /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,10}, 5 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,3 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP224R1
+{
+ /* curve name */ "BRAINPOOLP224R1",
+ /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
+ /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
+ /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
+ /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
+ /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
+ /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,5 }, 10
},
#endif
#ifdef LTC_ECC_BRAINPOOLP256R1
{
- /* size/bytes */ 32,
/* curve name */ "BRAINPOOLP256R1",
/* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
/* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
@@ -335,12 +333,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
/* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,7}, 10 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,7 }, 10
},
#endif
#ifdef LTC_ECC_BRAINPOOLP320R1
{
- /* size/bytes */ 40,
/* curve name */ "BRAINPOOLP320R1",
/* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
/* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
@@ -349,26 +346,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
/* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,9}, 10 }
-},
-#endif
-#if defined(LTC_ECC_SECP384R1) || defined(LTC_ECC384)
-{ /* this curve ***MUST*** be the first from all with size 48 (backward compatibility reasons) */
- /* size/bytes */ 48,
- /* curve name */ "SECP384R1", /* same as: NISTP384, old libtomcrypt name: ECC-384 */
- /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
- /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
- /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
- /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
- /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
- /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
- /* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,34}, 5 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,9 }, 10
},
#endif
#ifdef LTC_ECC_BRAINPOOLP384R1
{
- /* size/bytes */ 48,
/* curve name */ "BRAINPOOLP384R1",
/* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
/* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
@@ -377,12 +359,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
/* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,11}, 10 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,11 }, 10
},
#endif
#ifdef LTC_ECC_BRAINPOOLP512R1
{
- /* size/bytes */ 64,
/* curve name */ "BRAINPOOLP512R1",
/* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
/* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
@@ -391,28 +372,104 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
/* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,13}, 10 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,13 }, 10
},
#endif
-#if defined(LTC_ECC_SECP521R1) || defined(LTC_ECC521)
-{ /* this curve ***MUST*** be the first from all with size 66 (backward compatibility reasons) */
- /* size/bytes */ 66,
- /* curve name */ "SECP521R1", /* same as: NISTP521, old libtomcrypt name: ECC-521 */
- /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
- /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
- /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
- /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
- /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+#ifdef LTC_ECC_BRAINPOOLP160T1
+{
+ /* curve name */ "BRAINPOOLP160T1",
+ /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
+ /* A */ "E95E4A5F737059DC60DFC7AD95B3D8139515620C",
+ /* B */ "7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380",
+ /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
+ /* Gx */ "B199B13B9B34EFC1397E64BAEB05ACC265FF2378",
+ /* Gy */ "ADD6718B7C7C1961F0991B842443772152C9E0AD",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,35}, 5 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,2 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP192T1
+{
+ /* curve name */ "BRAINPOOLP192T1",
+ /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
+ /* A */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294",
+ /* B */ "13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79",
+ /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
+ /* Gx */ "3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129",
+ /* Gy */ "097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,4 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP224T1
+{
+ /* curve name */ "BRAINPOOLP224T1",
+ /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
+ /* A */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC",
+ /* B */ "4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D",
+ /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
+ /* Gx */ "6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580",
+ /* Gy */ "0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,6 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP256T1
+{
+ /* curve name */ "BRAINPOOLP256T1",
+ /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
+ /* A */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374",
+ /* B */ "662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04",
+ /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
+ /* Gx */ "A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4",
+ /* Gy */ "2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,8 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP320T1
+{
+ /* curve name */ "BRAINPOOLP320T1",
+ /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
+ /* A */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24",
+ /* B */ "A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353",
+ /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
+ /* Gx */ "925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52",
+ /* Gy */ "63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,10 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP384T1
+{
+ /* curve name */ "BRAINPOOLP384T1",
+ /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
+ /* A */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50",
+ /* B */ "7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE",
+ /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
+ /* Gx */ "18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC",
+ /* Gy */ "25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,12 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP512T1
+{
+ /* curve name */ "BRAINPOOLP512T1",
+ /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
+ /* A */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0",
+ /* B */ "7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E",
+ /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
+ /* Gx */ "640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA",
+ /* Gy */ "5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,14 }, 10
},
#endif
{
- 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0,
- { { 0 }, 0 }
+ { 0 }, 0
}
};
diff --git a/src/ltc/pk/ecc/ecc_ansi_x963_export.c b/src/ltc/pk/ecc/ecc_ansi_x963_export.c
index 8bb4cc5f..528dcd80 100644
--- a/src/ltc/pk/ecc/ecc_ansi_x963_export.c
+++ b/src/ltc/pk/ecc/ecc_ansi_x963_export.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -34,10 +31,7 @@ int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
- if (ltc_ecc_is_valid_idx(key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
- numlen = key->dp->size;
+ numlen = key->dp.size;
xlen = mp_unsigned_bin_size(key->pubkey.x);
ylen = mp_unsigned_bin_size(key->pubkey.y);
diff --git a/src/ltc/pk/ecc/ecc_ansi_x963_import.c b/src/ltc/pk/ecc/ecc_ansi_x963_import.c
index 9c5a84e5..bcc8575f 100644
--- a/src/ltc/pk/ecc/ecc_ansi_x963_import.c
+++ b/src/ltc/pk/ecc/ecc_ansi_x963_import.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -29,9 +26,9 @@ int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *
return ecc_ansi_x963_import_ex(in, inlen, key, NULL);
}
-int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp)
+int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp)
{
- int x, err;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
@@ -41,60 +38,21 @@ int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_ke
return CRYPT_INVALID_ARG;
}
- /* init key */
- if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
- /* check for 4, 6 or 7 */
- if (in[0] != 4 && in[0] != 6 && in[0] != 7) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
-
- /* read data */
- if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)in+1, (inlen-1)>>1)) != CRYPT_OK) {
- goto error;
+ /* initialize key->dp */
+ if (dp == NULL) {
+ /* this case works only for uncompressed public keys */
+ if ((err = ecc_set_dp_size((inlen-1)>>1, key)) != CRYPT_OK) { return err; }
}
-
- if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)in+1+((inlen-1)>>1), (inlen-1)>>1)) != CRYPT_OK) {
- goto error;
+ else {
+ /* this one works for both compressed / uncompressed pubkeys */
+ if ((err = ecc_set_dp(dp, key)) != CRYPT_OK) { return err; }
}
- if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
- if (dp == NULL) {
- /* BEWARE: Here we are looking up the curve params by keysize (neither curve name nor curve oid),
- * which might be ambiguous (there can more than one curve for given keysize).
- * Thus the chosen curve depends on order of items in ltc_ecc_sets[] - see ecc.c file.
- */
- /* determine the idx */
- for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
- if ((unsigned)ltc_ecc_sets[x].size >= ((inlen-1)>>1)) {
- break;
- }
- }
- if (ltc_ecc_sets[x].size == 0) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
- /* set the idx */
- key->idx = x;
- key->dp = &ltc_ecc_sets[x];
- } else {
- if (((inlen-1)>>1) != (unsigned long) dp->size) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
- key->idx = -1;
- key->dp = dp;
- }
- key->type = PK_PUBLIC;
+ /* load public key */
+ if ((err = ecc_set_key((unsigned char *)in, inlen, PK_PUBLIC, key)) != CRYPT_OK) { return err; }
/* we're done */
return CRYPT_OK;
-error:
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
- return err;
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_decrypt_key.c b/src/ltc/pk/ecc/ecc_decrypt_key.c
index d86c168b..ebfa5156 100644
--- a/src/ltc/pk/ecc/ecc_decrypt_key.c
+++ b/src/ltc/pk/ecc/ecc_decrypt_key.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -33,7 +30,8 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
ecc_key *key)
{
unsigned char *ecc_shared, *skey, *pub_expt;
- unsigned long x, y, hashOID[32];
+ unsigned long x, y;
+ unsigned long hashOID[32] = { 0 };
int hash, err;
ecc_key pubkey;
ltc_asn1_list decode[3];
@@ -87,9 +85,8 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
}
/* import ECC key from packet */
- if ((err = ecc_import_raw(decode[1].data, decode[1].size, &pubkey, (ltc_ecc_set_type *)key->dp)) != CRYPT_OK) {
- goto LBL_ERR;
- }
+ if ((err = ecc_set_dp_copy(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
/* make shared key */
x = ECC_BUF_SIZE;
diff --git a/src/ltc/pk/ecc/ecc_dp_clear.c b/src/ltc/pk/ecc/ecc_dp_clear.c
deleted file mode 100644
index 76fa375e..00000000
--- a/src/ltc/pk/ecc/ecc_dp_clear.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_dp_clear(ltc_ecc_set_type *dp)
-{
- if (dp == NULL) return CRYPT_INVALID_ARG;
-
- if (dp->name != NULL) { XFREE(dp->name ); dp->name = NULL; }
- if (dp->prime != NULL) { XFREE(dp->prime); dp->prime = NULL; }
- if (dp->A != NULL) { XFREE(dp->A ); dp->A = NULL; }
- if (dp->B != NULL) { XFREE(dp->B ); dp->B = NULL; }
- if (dp->order != NULL) { XFREE(dp->order); dp->order = NULL; }
- if (dp->Gx != NULL) { XFREE(dp->Gx ); dp->Gx = NULL; }
- if (dp->Gy != NULL) { XFREE(dp->Gy ); dp->Gy = NULL; }
- dp->cofactor = 0;
- dp->oid.OIDlen = 0;
-
- return CRYPT_OK;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_fill_from_sets.c b/src/ltc/pk/ecc/ecc_dp_fill_from_sets.c
deleted file mode 100644
index 06c66be4..00000000
--- a/src/ltc/pk/ecc/ecc_dp_fill_from_sets.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-static int hexstrcmp(const char *hexa, const char *hexb)
-{
- #define MY_TOLOWER(a) ((((a)>='A')&&((a)<='Z')) ? ((a)|0x60) : (a))
- /* ignore leading zeroes */
- while(*hexa == '0') hexa++;
- while(*hexb == '0') hexb++;
- /* compare: case insensitive, hexadecimal chars only */
- while (*hexa && *hexb) {
- if ( (*hexa < '0' || *hexa > '9') &&
- (*hexa < 'a' || *hexa > 'f') &&
- (*hexa < 'A' || *hexa > 'F') ) return 1;
- if ( (*hexb < '0' || *hexb > '9') &&
- (*hexb < 'a' || *hexb > 'f') &&
- (*hexb < 'A' || *hexb > 'F') ) return 1;
- if (MY_TOLOWER(*hexa) != MY_TOLOWER(*hexb)) return 1;
- hexa++;
- hexb++;
- }
- if (*hexa == '\0' && *hexb == '\0') return 0; /* success - match */
- return 1;
-}
-
-/* search known curve by curve parameters and fill in missing parameters into dp
- * we assume every parameter has the same case (usually uppercase) and no leading zeros
- */
-int ecc_dp_fill_from_sets(ltc_ecc_set_type *dp)
-{
- ltc_ecc_set_type params;
- int x;
-
- if (!dp) return CRYPT_INVALID_ARG;
- if (dp->oid.OIDlen > 0) return CRYPT_OK;
- if (!dp->prime || !dp->A || !dp->B || !dp->order || !dp->Gx || !dp->Gy || dp->cofactor == 0) return CRYPT_INVALID_ARG;
-
- for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
- if (hexstrcmp(ltc_ecc_sets[x].prime, dp->prime) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].A, dp->A) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].B, dp->B) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].order, dp->order) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].Gx, dp->Gx) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].Gy, dp->Gy) == 0 &&
- ltc_ecc_sets[x].cofactor == dp->cofactor) {
-
- params = ltc_ecc_sets[x];
-
- /* copy oid */
- dp->oid.OIDlen = params.oid.OIDlen;
- XMEMCPY(dp->oid.OID, params.oid.OID, dp->oid.OIDlen * sizeof(dp->oid.OID[0]));
-
- /* copy name */
- if (dp->name != NULL) XFREE(dp->name);
- if ((dp->name = XMALLOC(1+strlen(params.name))) == NULL) return CRYPT_MEM;
- strcpy(dp->name, params.name);
-
- return CRYPT_OK;
- }
- }
-
- return CRYPT_INVALID_ARG;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_from_oid.c b/src/ltc/pk/ecc/ecc_dp_from_oid.c
deleted file mode 100644
index 5ddd1aba..00000000
--- a/src/ltc/pk/ecc/ecc_dp_from_oid.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* 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.
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_dp_set_by_oid(ltc_ecc_set_type *dp, unsigned long *oid, unsigned long oidsize)
-{
- int i;
- unsigned long len;
-
- for(i=0; ltc_ecc_sets[i].size != 0; i++) {
- if ((oidsize == ltc_ecc_sets[i].oid.OIDlen) &&
- (XMEM_NEQ(oid, ltc_ecc_sets[i].oid.OID, sizeof(unsigned long) * ltc_ecc_sets[i].oid.OIDlen) == 0)) {
- break;
- }
- }
- if (ltc_ecc_sets[i].size == 0) return CRYPT_INVALID_ARG; /* not found */
-
- /* a */
- len = (unsigned long)strlen(ltc_ecc_sets[i].A);
- if ((dp->A = XMALLOC(1+len)) == NULL) goto cleanup1;
- strncpy(dp->A, ltc_ecc_sets[i].A, 1+len);
- /* b */
- len = (unsigned long)strlen(ltc_ecc_sets[i].B);
- if ((dp->B = XMALLOC(1+len)) == NULL) goto cleanup2;
- strncpy(dp->B, ltc_ecc_sets[i].B, 1+len);
- /* order */
- len = (unsigned long)strlen(ltc_ecc_sets[i].order);
- if ((dp->order = XMALLOC(1+len)) == NULL) goto cleanup3;
- strncpy(dp->order, ltc_ecc_sets[i].order, 1+len);
- /* prime */
- len = (unsigned long)strlen(ltc_ecc_sets[i].prime);
- if ((dp->prime = XMALLOC(1+len)) == NULL) goto cleanup4;
- strncpy(dp->prime, ltc_ecc_sets[i].prime, 1+len);
- /* gx */
- len = (unsigned long)strlen(ltc_ecc_sets[i].Gx);
- if ((dp->Gx = XMALLOC(1+len)) == NULL) goto cleanup5;
- strncpy(dp->Gx, ltc_ecc_sets[i].Gx, 1+len);
- /* gy */
- len = (unsigned long)strlen(ltc_ecc_sets[i].Gy);
- if ((dp->Gy = XMALLOC(1+len)) == NULL) goto cleanup6;
- strncpy(dp->Gy, ltc_ecc_sets[i].Gy, 1+len);
- /* cofactor & size */
- dp->cofactor = ltc_ecc_sets[i].cofactor;
- dp->size = ltc_ecc_sets[i].size;
- /* name */
- len = (unsigned long)strlen(ltc_ecc_sets[i].name);
- if ((dp->name = XMALLOC(1+len)) == NULL) goto cleanup7;
- strncpy(dp->name, ltc_ecc_sets[i].name, 1+len);
- /* oid */
- dp->oid.OIDlen = ltc_ecc_sets[i].oid.OIDlen;
- XMEMCPY(dp->oid.OID, ltc_ecc_sets[i].oid.OID, dp->oid.OIDlen * sizeof(dp->oid.OID[0]));
- /* done - success */
- return CRYPT_OK;
-
-cleanup7:
- XFREE(dp->Gy);
-cleanup6:
- XFREE(dp->Gx);
-cleanup5:
- XFREE(dp->prime);
-cleanup4:
- XFREE(dp->order);
-cleanup3:
- XFREE(dp->B);
-cleanup2:
- XFREE(dp->A);
-cleanup1:
- return CRYPT_MEM;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_from_params.c b/src/ltc/pk/ecc/ecc_dp_from_params.c
deleted file mode 100644
index a1ddee97..00000000
--- a/src/ltc/pk/ecc/ecc_dp_from_params.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* 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.
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_dp_set_bn(ltc_ecc_set_type *dp, void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor)
-{
- unsigned char buf[ECC_BUF_SIZE];
- unsigned long len;
-
- /* a */
- mp_tohex(a, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->A = XMALLOC(1+len)) == NULL) goto cleanup1;
- strncpy(dp->A, (char*)buf, 1+len);
- /* b */
- mp_tohex(b, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->B = XMALLOC(1+len)) == NULL) goto cleanup2;
- strncpy(dp->B, (char*)buf, 1+len);
- /* order */
- mp_tohex(order, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->order = XMALLOC(1+len)) == NULL) goto cleanup3;
- strncpy(dp->order, (char*)buf, 1+len);
- /* prime */
- mp_tohex(prime, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->prime = XMALLOC(1+len)) == NULL) goto cleanup4;
- strncpy(dp->prime, (char*)buf, 1+len);
- /* gx */
- mp_tohex(gx, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->Gx = XMALLOC(1+len)) == NULL) goto cleanup5;
- strncpy(dp->Gx, (char*)buf, 1+len);
- /* gy */
- mp_tohex(gy, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->Gy = XMALLOC(1+len)) == NULL) goto cleanup6;
- strncpy(dp->Gy, (char*)buf, 1+len);
- /* cofactor & size */
- dp->cofactor = cofactor;
- dp->size = mp_unsigned_bin_size(prime);
- /* see if we can fill in the missing parameters from known curves */
- if ((ecc_dp_fill_from_sets(dp)) != CRYPT_OK) {
- /* custom name */
- if ((dp->name = XMALLOC(7)) == NULL) goto cleanup7;
- strcpy(dp->name, "custom"); /* XXX-TODO check this */
- /* no oid */
- dp->oid.OIDlen = 0;
- }
- /* done - success */
- return CRYPT_OK;
-
- /* XFREE(dp->name); **** warning: statement not reached *** */
-cleanup7:
- XFREE(dp->Gy);
-cleanup6:
- XFREE(dp->Gx);
-cleanup5:
- XFREE(dp->prime);
-cleanup4:
- XFREE(dp->order);
-cleanup3:
- XFREE(dp->B);
-cleanup2:
- XFREE(dp->A);
-cleanup1:
- return CRYPT_MEM;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_init.c b/src/ltc/pk/ecc/ecc_dp_init.c
deleted file mode 100644
index 36c8f5c6..00000000
--- a/src/ltc/pk/ecc/ecc_dp_init.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_dp_init(ltc_ecc_set_type *dp)
-{
- if (dp == NULL) return CRYPT_INVALID_ARG;
-
- dp->name = NULL;
- dp->prime = NULL;
- dp->A = NULL;
- dp->B = NULL;
- dp->order = NULL;
- dp->Gx = NULL;
- dp->Gy = NULL;
- dp->oid.OIDlen = 0;
- dp->cofactor = 0;
-
- return CRYPT_OK;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_set.c b/src/ltc/pk/ecc/ecc_dp_set.c
deleted file mode 100644
index 33c72816..00000000
--- a/src/ltc/pk/ecc/ecc_dp_set.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* 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.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-#include <errno.h>
-
-#ifdef LTC_MECC
-
-int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name, char *oid)
-{
- unsigned long l_name, l_prime, l_A, l_B, l_order, l_Gx, l_Gy;
-
- if (!dp || !ch_prime || !ch_A || !ch_B || !ch_order || !ch_Gx || !ch_Gy || cofactor==0) return CRYPT_INVALID_ARG;
-
- l_prime = (unsigned long)strlen(ch_prime);
- l_A = (unsigned long)strlen(ch_A);
- l_B = (unsigned long)strlen(ch_B);
- l_order = (unsigned long)strlen(ch_order);
- l_Gx = (unsigned long)strlen(ch_Gx);
- l_Gy = (unsigned long)strlen(ch_Gy);
-
- dp->cofactor = cofactor;
-
- { /* calculate size */
- void *p_num;
- mp_init(&p_num);
- mp_read_radix(p_num, ch_prime, 16);
- dp->size = mp_unsigned_bin_size(p_num);
- mp_clear(p_num);
- }
-
- if (dp->name != NULL) { XFREE(dp->name ); dp->name = NULL; }
- if (dp->prime != NULL) { XFREE(dp->prime); dp->prime = NULL; }
- if (dp->A != NULL) { XFREE(dp->A ); dp->A = NULL; }
- if (dp->B != NULL) { XFREE(dp->B ); dp->B = NULL; }
- if (dp->order != NULL) { XFREE(dp->order); dp->order = NULL; }
- if (dp->Gx != NULL) { XFREE(dp->Gx ); dp->Gx = NULL; }
- if (dp->Gy != NULL) { XFREE(dp->Gy ); dp->Gy = NULL; }
-
- dp->prime = XMALLOC(1+l_prime); strncpy(dp->prime, ch_prime, 1+l_prime);
- dp->A = XMALLOC(1+l_A); strncpy(dp->A, ch_A, 1+l_A);
- dp->B = XMALLOC(1+l_B); strncpy(dp->B, ch_B, 1+l_B);
- dp->order = XMALLOC(1+l_order); strncpy(dp->order, ch_order, 1+l_order);
- dp->Gx = XMALLOC(1+l_Gx); strncpy(dp->Gx, ch_Gx, 1+l_Gx);
- dp->Gy = XMALLOC(1+l_Gy); strncpy(dp->Gy, ch_Gy, 1+l_Gy);
-
- /* optional parameters */
- if (ch_name == NULL && oid == NULL) {
- (void)ecc_dp_fill_from_sets(dp);
- }
- else {
- if (ch_name != NULL) {
- l_name = (unsigned long)strlen(ch_name);
- dp->name = XMALLOC(1+l_name);
- strncpy(dp->name, ch_name, 1+l_name);
- }
-
- if (oid != NULL) {
- char *end_ptr;
- unsigned int i = 0;
- unsigned long val;
-
- end_ptr = oid;
- while (i < sizeof(dp->oid.OID)/sizeof(dp->oid.OID[0]) && *oid != '\0') {
- errno = 0;
- val = strtoul(oid, &end_ptr, 10);
- if (errno != 0 || oid == end_ptr) break; /* parsing failed */
- if (val > 0xFFFFFFFF) break; /* x64 check */
- dp->oid.OID[i++] = val;
- oid = end_ptr;
- if (*oid != '.') break;
- oid++;
- }
- if (i == 0 || *end_ptr != '\0') return CRYPT_INVALID_ARG;
- dp->oid.OIDlen = i;
- }
- }
-
- /* in case the parameters are really custom (unlikely) */
- if (dp->name == NULL) {
- dp->name = XMALLOC(7);
- strcpy(dp->name, "custom");
- dp->oid.OIDlen = 0;
- }
-
- return CRYPT_OK;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_encrypt_key.c b/src/ltc/pk/ecc/ecc_encrypt_key.c
index 8a32190b..530eadd8 100644
--- a/src/ltc/pk/ecc/ecc_encrypt_key.c
+++ b/src/ltc/pk/ecc/ecc_encrypt_key.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -60,9 +57,8 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
}
/* make a random key and export the public copy */
- if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {
- return err;
- }
+ if ((err = ecc_set_dp_copy(key, &pubkey)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; }
pub_expt = XMALLOC(ECC_BUF_SIZE);
ecc_shared = XMALLOC(ECC_BUF_SIZE);
@@ -82,7 +78,12 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
}
pubkeysize = ECC_BUF_SIZE;
- if ((err = ecc_export_raw(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey)) != CRYPT_OK) {
+#ifdef USE_TFM
+ /* XXX-FIXME: TFM does not support sqrtmod_prime */
+ if ((err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
+#else
+ if ((err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey)) != CRYPT_OK) {
+#endif
ecc_free(&pubkey);
goto LBL_ERR;
}
diff --git a/src/ltc/pk/ecc/ecc_export.c b/src/ltc/pk/ecc/ecc_export.c
index 05aacfed..a095e9a2 100644
--- a/src/ltc/pk/ecc/ecc_export.c
+++ b/src/ltc/pk/ecc/ecc_export.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -42,12 +39,8 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key
return CRYPT_PK_TYPE_MISMATCH;
}
- if (ltc_ecc_is_valid_idx(key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
-
/* we store the NIST byte size */
- key_size = key->dp->size;
+ key_size = key->dp.size;
if (type == PK_PRIVATE) {
flags[0] = 1;
diff --git a/src/ltc/pk/ecc/ecc_export_full.c b/src/ltc/pk/ecc/ecc_export_openssl.c
index e7d940d5..c9181376 100644
--- a/src/ltc/pk/ecc/ecc_export_full.c
+++ b/src/ltc/pk/ecc/ecc_export_openssl.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -25,7 +20,7 @@
@return CRYPT_OK if successful
*/
-int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
+int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
{
int err;
void *prime, *order, *a, *b, *gx, *gy;
@@ -33,24 +28,23 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
unsigned long len_a, len_b, len_k, len_g, len_xy;
unsigned long cofactor, one = 1;
oid_st oid;
- ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], asn_ecparams[1];
+ ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], pub_xy, ecparams;
+ int flag_oid = type & PK_CURVEOID ? 1 : 0;
+ int flag_com = type & PK_COMPRESSED ? 1 : 0;
+ int flag_pri = type & PK_PRIVATE ? 1 : 0;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(key != NULL);
- if (key->type != PK_PRIVATE && type == PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
- if (ltc_ecc_is_valid_idx(key->idx) == 0) return CRYPT_INVALID_ARG;
- if (key->dp == NULL) return CRYPT_INVALID_ARG;
-
- if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) return err;
+ if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH;
- if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(order, key->dp->order, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(a, key->dp->A, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(gx, key->dp->Gx, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(gy, key->dp->Gy, 16)) != CRYPT_OK) goto error;
+ prime = key->dp.prime;
+ order = key->dp.order;
+ b = key->dp.B;
+ a = key->dp.A;
+ gx = key->dp.base.x;
+ gy = key->dp.base.y;
/* curve param a */
len_a = mp_unsigned_bin_size(a);
@@ -64,33 +58,32 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) goto error;
if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* XXX-TODO hack to handle case b == 0 */
- /* base point - we export uncompressed form */
+ /* base point - (un)compressed based on flag_com */
len_g = sizeof(bin_g);
- if ((err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp->size, 0)) != CRYPT_OK) goto error;
+ if ((err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com)) != CRYPT_OK) goto error;
- /* public key */
+ /* public key - (un)compressed based on flag_com */
len_xy = sizeof(bin_xy);
- if ((err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp->size, 0)) != CRYPT_OK) goto error;
+ if ((err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com)) != CRYPT_OK) goto error;
/* co-factor */
- cofactor = key->dp->cofactor;
+ cofactor = key->dp.cofactor;
/* we support only prime-field EC */
- if ((err = pk_get_oid(EC_PRIME_FIELD, &oid)) != CRYPT_OK) goto error;
+ if ((err = pk_get_oid(PKA_EC_PRIMEF, &oid)) != CRYPT_OK) goto error;
- if (type & PK_CURVEOID) {
+ if (flag_oid) {
/* from http://tools.ietf.org/html/rfc5912
ECParameters ::= CHOICE {
namedCurve CURVE.&id({NamedCurve}) # OBJECT
}
*/
-
- /* BEWARE: exporting PK_CURVEOID with custom OID means we're unable to read the curve again */
- if (key->dp->oid.OIDlen == 0) { err = CRYPT_INVALID_ARG; goto error; }
-
- /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */
- LTC_SET_ASN1(asn_ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp->oid.OID, key->dp->oid.OIDlen);
+ if (key->dp.oidlen == 0) {
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen);
}
else {
/* from http://tools.ietf.org/html/rfc3279
@@ -129,12 +122,10 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
/* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */
- LTC_SET_ASN1(asn_ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
+ LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
}
- type &= ~PK_CURVEOID;
-
- if (type == PK_PRIVATE) {
+ if (flag_pri) {
/* private key format: http://tools.ietf.org/html/rfc5915
ECPrivateKey ::= SEQUENCE { # SEQUENCE
@@ -150,12 +141,11 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; }
if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) goto error;
- LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
- LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k);
- LTC_SET_ASN1(seq_priv, 2, asn_ecparams[0].type, asn_ecparams[0].data, asn_ecparams[0].size);
- LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy);
- seq_priv[2].tag = 0xA0;
- seq_priv[3].tag = 0xA1;
+ LTC_SET_ASN1(&pub_xy, 0, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy);
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k);
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, &ecparams); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, &pub_xy); /* context specific 1 */
err = der_encode_sequence(seq_priv, 4, out, outlen);
}
@@ -170,14 +160,17 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
subjectPublicKey BIT STRING # BIT STRING
}
*/
- err = der_encode_subject_public_key_info( out, outlen,
+ err = x509_encode_subject_public_key_info( out, outlen,
PKA_EC, bin_xy, len_xy,
- asn_ecparams[0].type, asn_ecparams[0].data, asn_ecparams[0].size );
+ ecparams.type, ecparams.data, ecparams.size );
}
error:
- mp_clear_multi(prime, order, a, b, gx, gy, NULL);
return err;
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_free.c b/src/ltc/pk/ecc/ecc_free.c
index e25d7c58..c8033b3b 100644
--- a/src/ltc/pk/ecc/ecc_free.c
+++ b/src/ltc/pk/ecc/ecc_free.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -26,7 +23,14 @@
void ecc_free(ecc_key *key)
{
LTC_ARGCHKVD(key != NULL);
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+ /* clean dp */
+ mp_cleanup_multi(&key->dp.prime, &key->dp.order,
+ &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ NULL);
+
+ /* clean key */
+ mp_cleanup_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_export_raw.c b/src/ltc/pk/ecc/ecc_get_key.c
index ed4966dd..2b4e8574 100644
--- a/src/ltc/pk/ecc/ecc_export_raw.c
+++ b/src/ltc/pk/ecc/ecc_get_key.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -24,7 +19,7 @@
Return CRYPT_OK on success
*/
-int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
+int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
{
unsigned long size, ksize;
int err, compressed;
@@ -33,19 +28,14 @@ int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
- if (ltc_ecc_is_valid_idx(key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
- size = key->dp->size;
-
- compressed = type & PK_COMPRESSED;
+ size = key->dp.size;
+ compressed = type & PK_COMPRESSED ? 1 : 0;
type &= ~PK_COMPRESSED;
- if (type == PK_PUBLIC && compressed) {
- if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, 1)) != CRYPT_OK) return err;
- }
- else if (type == PK_PUBLIC) {
- if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, 0)) != CRYPT_OK) return err;
+ if (type == PK_PUBLIC) {
+ if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, compressed)) != CRYPT_OK) {
+ return err;
+ }
}
else if (type == PK_PRIVATE) {
if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
@@ -64,3 +54,7 @@ int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_get_set.c b/src/ltc/pk/ecc/ecc_get_set.c
new file mode 100644
index 00000000..f00cf45f
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_get_set.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+int ecc_get_set_by_name(const char* name, const ltc_ecc_set_type** dp)
+{
+ int i;
+
+ LTC_ARGCHK(dp != NULL);
+ LTC_ARGCHK(name != NULL);
+
+ *dp = NULL;
+
+ for (i = 0; ltc_ecc_sets[i].name != NULL; i++) {
+ if (XSTRCMP(ltc_ecc_sets[i].name, name) == 0) break;
+ }
+
+ if (ltc_ecc_sets[i].name == NULL) {
+ /* not found */
+ return CRYPT_INVALID_ARG;
+ }
+
+ *dp = &ltc_ecc_sets[i];
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_get_size.c b/src/ltc/pk/ecc/ecc_get_size.c
index f77ab8b3..8d1c9362 100644
--- a/src/ltc/pk/ecc/ecc_get_size.c
+++ b/src/ltc/pk/ecc/ecc_get_size.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -26,11 +23,10 @@
*/
int ecc_get_size(ecc_key *key)
{
- LTC_ARGCHK(key != NULL);
- if (ltc_ecc_is_valid_idx(key->idx))
- return key->dp->size;
- else
- return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
+ if (key == NULL) {
+ return INT_MAX;
+ }
+ return key->dp.size;
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_import.c b/src/ltc/pk/ecc/ecc_import.c
index 38465b12..3a1dcc57 100644
--- a/src/ltc/pk/ecc/ecc_import.c
+++ b/src/ltc/pk/ecc/ecc_import.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -49,18 +46,20 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
- /* init key */
- if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
/* find out what type of key it is */
- err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
- LTC_ASN1_EOL, 0UL, NULL);
+ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_EOL, 0UL, NULL);
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
- goto done;
+ return err;
}
+ /* allocate & initialize the key */
+ if (dp == NULL) {
+ if ((err = ecc_set_dp_size(key_size, key)) != CRYPT_OK) { goto done; }
+ } else {
+ if ((err = ecc_set_dp(dp, key)) != CRYPT_OK) { goto done; }
+ }
if (flags[0] == 1) {
/* private key */
@@ -91,30 +90,17 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co
goto done;
}
- if (dp == NULL) {
- /* find the idx */
- for (key->idx = 0; ltc_ecc_sets[key->idx].size && (unsigned long)ltc_ecc_sets[key->idx].size != key_size; ++key->idx);
- if (ltc_ecc_sets[key->idx].size == 0) {
- err = CRYPT_INVALID_PACKET;
- goto done;
- }
- key->dp = &ltc_ecc_sets[key->idx];
- } else {
- key->idx = -1;
- key->dp = dp;
- }
/* set z */
if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; }
- /* is it a point on the curve? */
- if ((err = ltc_ecc_is_point(key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) {
- goto done;
- }
+ /* point on the curve + other checks */
+ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; }
/* we're good */
return CRYPT_OK;
+
done:
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+ ecc_free(key);
return err;
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_import_full.c b/src/ltc/pk/ecc/ecc_import_full.c
deleted file mode 100644
index 0e5093d4..00000000
--- a/src/ltc/pk/ecc/ecc_import_full.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* 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.
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_import_full(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp)
-{
- void *prime, *order, *a, *b, *gx, *gy;
- ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4];
- unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE], bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
- unsigned long len_a, len_b, len_k, len_g, len_xy, len_oid;
- unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16], curveoid[16];
- int err;
-
- if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) return err;
-
- /* ### 1. try to load public key - no curve parameters just curve OID */
-
- len_xy = sizeof(bin_xy);
- err = der_decode_subject_public_key_info_ex(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL, &len_oid);
- if (err == CRYPT_OK) {
- /* load curve parameters for given curve OID */
- if ((err = ecc_dp_set_by_oid(dp, curveoid, len_oid)) != CRYPT_OK) { goto error; }
- /* load public key */
- if ((err = ecc_import_raw(bin_xy, len_xy, key, dp)) != CRYPT_OK) { goto error; }
- goto success;
- }
-
- /* ### 2. try to load public key - curve parameters included */
-
- /* ECParameters SEQUENCE */
- LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
- LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
- LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
- LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
- LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
- LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
- seq_ecparams[5].optional = 1;
- /* FieldID SEQUENCE */
- LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
- LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
- /* Curve SEQUENCE */
- LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
- seq_curve[2].optional = 1;
- /* try to load public key */
- len_xy = sizeof(bin_xy);
- err = der_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, 6);
-
- if (err == CRYPT_OK) {
- len_a = seq_curve[0].size;
- len_b = seq_curve[1].size;
- len_g = seq_ecparams[3].size;
- /* create bignums */
- if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
- if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
- if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
- /* load curve parameters */
- if ((err = ecc_dp_set_bn(dp, a, b, prime, order, gx, gy, cofactor)) != CRYPT_OK) { goto error; }
- /* load public key */
- if ((err = ecc_import_raw(bin_xy, len_xy, key, dp)) != CRYPT_OK) { goto error; }
- goto success;
- }
-
- /* ### 3. try to load private key - no curve parameters just curve OID */
-
- /* ECPrivateKey SEQUENCE */
- LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
- LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL);
- LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
- seq_priv[2].tag = 0xA0; /* context specific 0 */
- seq_priv[3].tag = 0xA1; /* context specific 1 */
- /* try to load private key */
- err = der_decode_sequence(in, inlen, seq_priv, 4);
-
- if (err == CRYPT_OK) {
- /* load curve parameters for given curve OID */
- if ((err = ecc_dp_set_by_oid(dp, curveoid, seq_priv[2].size)) != CRYPT_OK) { goto error; }
- /* load private+public key */
- if ((err = ecc_import_raw(bin_k, seq_priv[1].size, key, dp)) != CRYPT_OK) { goto error; }
- goto success;
- }
-
- /* ### 4. try to load private key - curve parameters included */
-
- /* ECPrivateKey SEQUENCE */
- LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
- LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
- LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
- seq_priv[2].tag = 0xA0; /* context specific 0 */
- seq_priv[3].tag = 0xA1; /* context specific 1 */
- /* ECParameters SEQUENCE */
- LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
- LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
- LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
- LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
- LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
- LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
- seq_ecparams[5].optional = 1;
- /* FieldID SEQUENCE */
- LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
- LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
- /* Curve SEQUENCE */
- LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
- seq_curve[2].optional = 1;
- /* try to load private key */
- err = der_decode_sequence(in, inlen, seq_priv, 4);
- if (err == CRYPT_OK) {
- len_k = seq_priv[1].size;
- len_xy = seq_priv[3].size;
- len_a = seq_curve[0].size;
- len_b = seq_curve[1].size;
- len_g = seq_ecparams[3].size;
- /* create bignums */
- if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
- if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
- if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
- /* load curve parameters */
- if ((err = ecc_dp_set_bn(dp, a, b, prime, order, gx, gy, cofactor)) != CRYPT_OK) { goto error; }
- /* load private+public key */
- if ((err = ecc_import_raw(bin_k, len_k, key, dp)) != CRYPT_OK) { goto error; }
- goto success;
- }
-
- /* ### 5. backward compatibility - try to load old-DER format */
- if ((err = ecc_import(in, inlen, key)) != CRYPT_OK) { goto error; }
-
-success:
- err = CRYPT_OK;
-error:
- mp_clear_multi(prime, order, a, b, gx, gy, NULL);
- return err;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_import_openssl.c b/src/ltc/pk/ecc/ecc_import_openssl.c
new file mode 100644
index 00000000..abbf5052
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_import_openssl.c
@@ -0,0 +1,157 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ void *prime, *order, *a, *b, *gx, *gy;
+ ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2];
+ unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE], bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
+ unsigned long len_a, len_b, len_k, len_g, len_xy, len_oid, len;
+ unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16], curveoid[16];
+ int err;
+
+ if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* ### 1. try to load public key - no curve parameters just curve OID */
+
+ len_xy = sizeof(bin_xy);
+ len_oid = 16;
+ err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, &len_oid);
+ if (err == CRYPT_OK) {
+ /* load curve parameters for given curve OID */
+ if ((err = ecc_set_dp_oid(curveoid, len_oid, key)) != CRYPT_OK) { goto error; }
+ /* load public key */
+ if ((err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key)) != CRYPT_OK) { goto error; }
+ goto success;
+ }
+
+ /* ### 2. try to load public key - curve parameters included */
+
+ /* ECParameters SEQUENCE */
+ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
+ LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
+ LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
+ LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
+ seq_ecparams[5].optional = 1;
+ /* FieldID SEQUENCE */
+ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
+ LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
+ /* Curve SEQUENCE */
+ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
+ seq_curve[2].optional = 1;
+ /* try to load public key */
+ len_xy = sizeof(bin_xy);
+ len = 6;
+ err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len);
+
+ if (err == CRYPT_OK) {
+ len_a = seq_curve[0].size;
+ len_b = seq_curve[1].size;
+ len_g = seq_ecparams[3].size;
+ /* create bignums */
+ if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
+ /* load curve parameters */
+ if ((err = ecc_set_dp_bn(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
+ /* load public key */
+ if ((err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key)) != CRYPT_OK) { goto error; }
+ goto success;
+ }
+
+ /* ### 3. try to load private key - no curve parameters just curve OID */
+
+ /* ECPrivateKey SEQUENCE */
+ LTC_SET_ASN1(custom, 0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL);
+ LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
+
+ /* try to load private key */
+ err = der_decode_sequence(in, inlen, seq_priv, 4);
+ if (err == CRYPT_OK) {
+ /* load curve parameters for given curve OID */
+ if ((err = ecc_set_dp_oid(curveoid, custom[0].size, key)) != CRYPT_OK) { goto error; }
+ /* load private+public key */
+ if ((err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key)) != CRYPT_OK) { goto error; }
+ goto success;
+ }
+
+ /* ### 4. try to load private key - curve parameters included */
+
+ /* ECPrivateKey SEQUENCE */
+ LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
+ LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
+ /* ECParameters SEQUENCE */
+ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
+ LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
+ LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
+ LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
+ seq_ecparams[5].optional = 1;
+ /* FieldID SEQUENCE */
+ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
+ LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
+ /* Curve SEQUENCE */
+ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
+ seq_curve[2].optional = 1;
+ /* try to load private key */
+ err = der_decode_sequence(in, inlen, seq_priv, 4);
+ if (err == CRYPT_OK) {
+ len_xy = custom[1].size;
+ len_k = seq_priv[1].size;
+ len_a = seq_curve[0].size;
+ len_b = seq_curve[1].size;
+ len_g = seq_ecparams[3].size;
+ /* create bignums */
+ if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
+ /* load curve parameters */
+ if ((err = ecc_set_dp_bn(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
+ /* load private+public key */
+ if ((err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key)) != CRYPT_OK) { goto error; }
+ goto success;
+ }
+
+ /* ### 5. backward compatibility - try to load old-DER format */
+
+ if ((err = ecc_import(in, inlen, key)) != CRYPT_OK) { goto error; }
+
+success:
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(prime, order, a, b, gx, gy, NULL);
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_import_pkcs8.c b/src/ltc/pk/ecc/ecc_import_pkcs8.c
index 85f8d218..6b5b0c71 100644
--- a/src/ltc/pk/ecc/ecc_import_pkcs8.c
+++ b/src/ltc/pk/ecc/ecc_import_pkcs8.c
@@ -7,153 +7,597 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
#include "tomcrypt.h"
#ifdef LTC_MECC
-int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
- const void *pwd, unsigned long pwdlen,
- ecc_key *key, ltc_ecc_set_type *dp)
+enum algorithm_oid {
+ PBE_MD2_DES, /* 0 */
+ PBE_MD2_RC2,
+ PBE_MD5_DES,
+ PBE_MD5_RC2,
+ PBE_SHA1_DES,
+ PBE_SHA1_RC2, /* 5 */
+ PBES2,
+ PBKDF2,
+ DES_CBC,
+ RC2_CBC,
+ DES_EDE3_CBC, /* 10 */
+ HMAC_WITH_SHA1,
+ HMAC_WITH_SHA224,
+ HMAC_WITH_SHA256,
+ HMAC_WITH_SHA384,
+ HMAC_WITH_SHA512, /* 15 */
+ PBE_SHA1_3DES
+};
+
+static const oid_st oid_list[] = {
+ { { 1,2,840,113549,1,5,1 }, 7 }, /* [0] http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */
+ { { 1,2,840,113549,1,5,4 }, 7 }, /* [1] http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */
+ { { 1,2,840,113549,1,5,3 }, 7 }, /* [2] http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */
+ { { 1,2,840,113549,1,5,6 }, 7 }, /* [3] http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */
+ { { 1,2,840,113549,1,5,10 }, 7 }, /* [4] http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */
+ { { 1,2,840,113549,1,5,11 }, 7 }, /* [5] http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */
+ { { 1,2,840,113549,1,5,13 }, 7 }, /* [6] http://www.oid-info.com/get/1.2.840.113549.1.5.13 pbes2 */
+ { { 1,2,840,113549,1,5,12 }, 7 }, /* [7] http://www.oid-info.com/get/1.2.840.113549.1.5.12 pBKDF2 */
+ { { 1,3,14,3,2,7 }, 6 }, /* [8] http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */
+ { { 1,2,840,113549,3,2 }, 6 }, /* [9] http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */
+ { { 1,2,840,113549,3,7 }, 6 }, /* [10] http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */
+ { { 1,2,840,113549,2,7 }, 6 }, /* [11] http://www.oid-info.com/get/1.2.840.113549.2.7 hmacWithSHA1 */
+ { { 1,2,840,113549,2,8 }, 6 }, /* [12] http://www.oid-info.com/get/1.2.840.113549.2.8 hmacWithSHA224 */
+ { { 1,2,840,113549,2,9 }, 6 }, /* [13] http://www.oid-info.com/get/1.2.840.113549.2.9 hmacWithSHA256 */
+ { { 1,2,840,113549,2,10 }, 6 }, /* [14] http://www.oid-info.com/get/1.2.840.113549.2.10 hmacWithSHA384 */
+ { { 1,2,840,113549,2,11 }, 6 }, /* [15] http://www.oid-info.com/get/1.2.840.113549.2.11 hmacWithSHA512 */
+ { { 1,2,840,113549,1,12,1,3 }, 8 }, /* [16] http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */
+ { { 0 }, 0 },
+};
+
+static int _simple_utf8_to_utf16(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen) {
+ unsigned long len = 0;
+ const unsigned char* in_end = in + inlen;
+ const ulong32 offset[6] = {
+ 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL
+ };
+ int err = CRYPT_ERROR;
+
+ while (in < in_end) {
+ ulong32 ch = 0;
+ unsigned short extra = 0; /* 0 */
+ if (*in >= 192) extra++; /* 1 */
+ if (*in >= 224) extra++; /* 2 */
+ if (*in >= 240) extra++; /* 3 */
+ if (*in >= 248) extra++; /* 4 */
+ if (*in >= 252) extra++; /* 5 */
+ if (in + extra >= in_end) goto ERROR;
+ switch (extra) {
+ case 5: ch += *in++; ch <<= 6;
+ case 4: ch += *in++; ch <<= 6;
+ case 3: ch += *in++; ch <<= 6;
+ case 2: ch += *in++; ch <<= 6;
+ case 1: ch += *in++; ch <<= 6;
+ case 0: ch += *in++;
+ }
+ ch -= offset[extra];
+ if (ch > 0xFFFF) goto ERROR;
+ if (*outlen >= len + 2) {
+ out[len] = (unsigned short)((ch >> 8) & 0xFF);
+ out[len + 1] = (unsigned char)(ch & 0xFF);
+ }
+ len += 2;
+ }
+
+ err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK;
+ *outlen = len;
+ERROR:
+ return err;
+}
+
+static int _kdf_pkcs12(int hash_id, const unsigned char *pw, unsigned long pwlen,
+ const unsigned char *salt, unsigned long saltlen,
+ unsigned int iterations, unsigned char purpose,
+ unsigned char *out, unsigned long outlen)
{
- int err;
- void *zero, *one, *iter;
- unsigned char *buf1=NULL, *buf2=NULL;
- unsigned long buf1len, buf2len;
- unsigned long oid[16];
- oid_st ecoid;
- ltc_asn1_list alg_seq[2], top_seq[3];
- ltc_asn1_list alg_seq_e[2], key_seq_e[2], top_seq_e[2];
- unsigned char *decrypted=NULL;
- unsigned long decryptedlen;
- void *prime, *order, *a, *b, *gx, *gy;
- ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4];
- unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE], bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
- unsigned long len_a, len_b, len_g;
- unsigned long cofactor = 0, ecver = 0, tmpoid[16], curveoid[16];
+ unsigned long u = hash_descriptor[hash_id].hashsize;
+ unsigned long v = hash_descriptor[hash_id].blocksize;
+ unsigned long c = (outlen + u - 1) / u;
+ unsigned long Slen = ((saltlen + v - 1) / v) * v;
+ unsigned long Plen = ((pwlen + v - 1) / v) * v;
+ unsigned long k = (Plen + Slen) / v;
+ unsigned long Alen, keylen = 0;
+ unsigned int tmp, i, j, n;
+ unsigned char ch;
+ unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE];
+ unsigned char *I = NULL, *key = NULL;
+ int err = CRYPT_ERROR;
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(key != NULL);
- LTC_ARGCHK(ltc_mp.name != NULL);
+ key = XMALLOC(u * c);
+ I = XMALLOC(Plen + Slen);
+ if (key == NULL || I == NULL) goto DONE;
- /* get EC alg oid */
- err = pk_get_oid(PKA_EC, &ecoid);
- if (err != CRYPT_OK) { goto LBL_NOFREE; }
+ for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */
+ for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen];
+ for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */
+
+ for (i = 0; i < c; i++) {
+ Alen = u; /* hash size */
+ err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, NULL); /* A = HASH(D || I) */
+ if (err != CRYPT_OK) goto DONE;
+ for (j = 1; j < iterations; j++) {
+ err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */
+ if (err != CRYPT_OK) goto DONE;
+ }
+ /* fill buffer B with A */
+ for (j = 0; j < v; j++) B[j] = A[j % Alen];
+ /* B += 1 */
+ for (j = v; j > 0; j--) {
+ if (++B[j - 1] != 0) break;
+ }
+ /* I_n += B */
+ for (n = 0; n < k; n++) {
+ ch = 0;
+ for (j = v; j > 0; j--) {
+ tmp = I[n * v + j - 1] + B[j - 1] + ch;
+ ch = (unsigned char)((tmp >> 8) & 0xFF);
+ I[n * v + j - 1] = (unsigned char)(tmp & 0xFF);
+ }
+ }
+ /* store derived key block */
+ for (j = 0; j < Alen; j++) key[keylen++] = A[j];
+ }
- /* alloc buffers */
- buf1len = inlen; /* approx. guess */
- buf1 = XMALLOC(buf1len);
- if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; }
- buf2len = inlen; /* approx. guess */
- buf2 = XMALLOC(buf2len);
- if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE; }
+ for (i = 0; i < outlen; i++) out[i] = key[i];
+ err = CRYPT_OK;
+DONE:
+ if (I) XFREE(I);
+ if (key) XFREE(key);
+ return err;
+}
- /* init key */
- err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, &zero, &one, &iter, NULL);
- if (err != CRYPT_OK) { goto LBL_NOCLEAR; }
-
- /* try to decode encrypted priv key */
- LTC_SET_ASN1(key_seq_e, 0, LTC_ASN1_OCTET_STRING, buf1, buf1len);
- LTC_SET_ASN1(key_seq_e, 1, LTC_ASN1_INTEGER, iter, 1UL);
- LTC_SET_ASN1(alg_seq_e, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
- LTC_SET_ASN1(alg_seq_e, 1, LTC_ASN1_SEQUENCE, key_seq_e, 2UL);
- LTC_SET_ASN1(top_seq_e, 0, LTC_ASN1_SEQUENCE, alg_seq_e, 2UL);
- LTC_SET_ASN1(top_seq_e, 1, LTC_ASN1_OCTET_STRING, buf2, buf2len);
- err=der_decode_sequence(in, inlen, top_seq_e, 2UL);
- if (err == CRYPT_OK) {
- LTC_UNUSED_PARAM(pwd);
- LTC_UNUSED_PARAM(pwdlen);
- /* unsigned long icount = mp_get_int(iter); */
- /* XXX: TODO decrypt buf1 with a key derived form password + salt + iter */
- /* fprintf(stderr, "XXX-DEBUG: gonna decrypt: iter=%ld salt.len=%ld encdata.len=%ld\n", icount, key_seq_e[0].size, top_seq_e[1].size); */
- err = CRYPT_PK_INVALID_TYPE;
- goto LBL_ERR;
+static int _oid_to_id(const unsigned long *oid, unsigned long oid_size)
+{
+ int i, j;
+ for (j = 0; oid_list[j].OIDlen > 0; j++) {
+ int match = 1;
+ if (oid_list[j].OIDlen != oid_size) continue;
+ for (i = 0; i < (int)oid_size && match; i++) if (oid_list[j].OID[i] != oid[i]) match = 0;
+ if (match) return j;
}
- else {
- decrypted = (unsigned char*)in;
- decryptedlen = inlen;
+ return -1;
+}
+
+static int _pbes1_decrypt(const unsigned char *enc_data, unsigned long enc_size,
+ const unsigned char *pass, unsigned long pass_size,
+ const unsigned char *salt, unsigned long salt_size,
+ unsigned long iterations,
+ const unsigned long *oid, unsigned long oid_size,
+ unsigned char *dec_data, unsigned long *dec_size)
+{
+ int id = _oid_to_id(oid, oid_size);
+ int err, hid = -1, cid = -1;
+ unsigned int keylen, blklen;
+ unsigned char key_iv[32] = { 0 }, pad;
+ unsigned long len = sizeof(key_iv), pwlen = pass_size;
+ symmetric_CBC cbc;
+ unsigned char *pw = NULL;
+
+ /* https://tools.ietf.org/html/rfc8018#section-6.1.2 */
+ if (id == PBE_MD2_DES || id == PBE_MD2_RC2) hid = find_hash("md2");
+ if (id == PBE_MD5_DES || id == PBE_MD5_RC2) hid = find_hash("md5");
+ if (id == PBE_SHA1_DES || id == PBE_SHA1_RC2 || id == PBE_SHA1_3DES) hid = find_hash("sha1");
+
+ if (id == PBE_MD2_RC2 || id == PBE_MD5_RC2 || id == PBE_SHA1_RC2) {
+ cid = find_cipher("rc2");
+ keylen = 8;
+ blklen = 8;
+ }
+ if (id == PBE_MD2_DES || id == PBE_MD5_DES || id == PBE_SHA1_DES) {
+ cid = find_cipher("des");
+ keylen = 8;
+ blklen = 8;
+ }
+ if (id == PBE_SHA1_3DES) {
+ cid = find_cipher("3des");
+ keylen = 24;
+ blklen = 8;
}
- /* try to decode unencrypted priv key - curve defined by OID */
- LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
- LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL);
- LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
- LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
- LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
- err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
- if (err == CRYPT_OK) {
- /* load curve parameters for given curve OID */
- err = ecc_dp_set_by_oid(dp, curveoid, alg_seq[1].size);
- if (err != CRYPT_OK) { goto LBL_ERR; }
+ if (id == PBE_SHA1_3DES) {
+ /* convert password to unicode/utf16-be */
+ pwlen = pass_size * 2;
+ pw = XMALLOC(pwlen + 2);
+ if (pw == NULL) goto LBL_ERROR;
+ if ((err = _simple_utf8_to_utf16(pass, pass_size, pw, &pwlen) != CRYPT_OK)) goto LBL_ERROR;
+ pw[pwlen++] = 0;
+ pw[pwlen++] = 0;
+ /* derive KEY */
+ if ((err = _kdf_pkcs12(hid, pw, pwlen, salt, salt_size, iterations, 1, key_iv, keylen)) != CRYPT_OK) goto LBL_ERROR;
+ /* derive IV */
+ if ((err = _kdf_pkcs12(hid, pw, pwlen, salt, salt_size, iterations, 2, key_iv+24, blklen)) != CRYPT_OK) goto LBL_ERROR;
}
else {
- /* try to decode unencrypted priv key - curve defined by params */
- /* ECParameters SEQUENCE */
- LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
- LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
- LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
- LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
- LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
- LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
- seq_ecparams[5].optional = 1;
- /* FieldID SEQUENCE */
- LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
- LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
- /* Curve SEQUENCE */
- LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
- /* */
- LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
- LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
- LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
- LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
- LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
- seq_curve[2].optional = 1;
- err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
- if (err != CRYPT_OK) { goto LBL_ERR; }
- len_a = seq_curve[0].size;
- len_b = seq_curve[1].size;
- len_g = seq_ecparams[3].size;
- /* create bignums */
- if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto LBL_ERR; }
- if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto LBL_ERR; }
- if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto LBL_ERR; }
- /* load curve parameters */
- if ((err = ecc_dp_set_bn(dp, a, b, prime, order, gx, gy, cofactor)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = pkcs_5_alg1(pass, pass_size, salt, iterations, hid, key_iv, &len)) != CRYPT_OK) goto LBL_ERROR;
+ /* the output has 16 bytes: [KEY-8-bytes][IV-8-bytes] */
}
- /* check alg oid */
- if ((alg_seq[0].size != ecoid.OIDlen) ||
- XMEMCMP(ecoid.OID, alg_seq[0].data, ecoid.OIDlen * sizeof(ecoid.OID[0]))) {
- err = CRYPT_PK_INVALID_TYPE;
- goto LBL_ERR;
+ if (hid != -1 && cid != -1) {
+ if (salt_size != 8 || enc_size < blklen) goto LBL_ERROR;
+ if ((err = cbc_start(cid, key_iv + keylen, key_iv, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(enc_data, dec_data, enc_size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ pad = dec_data[enc_size-1];
+ if (pad < 1 || pad > blklen) goto LBL_ERROR;
+ *dec_size = enc_size - pad;
+ return CRYPT_OK;
}
- /* ECPrivateKey SEQUENCE */
- LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
- LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
- seq_priv[2].tag = 0xA1; /* context specific 1 */
- /* try to load private key */
- err = der_decode_sequence(buf1, top_seq[2].size, seq_priv, 3);
- if (err != CRYPT_OK) { goto LBL_ERR; }
- /* load private+public key */
- if ((err = ecc_import_raw(bin_k, seq_priv[1].size, key, dp)) != CRYPT_OK) { goto LBL_ERR; }
- /* success */
+LBL_ERROR:
+ zeromem(key_iv, sizeof(key_iv));
+ if (pw) { zeromem(pw, pwlen); XFREE(pw); }
+ return CRYPT_INVALID_ARG;
+}
+
+static int _pbes2_pbkdf2_decrypt(const unsigned char *enc_data, unsigned long enc_size,
+ const unsigned char *pass, unsigned long pass_size,
+ const unsigned char *salt, unsigned long salt_size,
+ const unsigned char *iv, unsigned long iv_size,
+ unsigned long iterations,
+ int hmacid,
+ int encid,
+ int extra_arg,
+ unsigned char *dec_data, unsigned long *dec_size)
+{
+ int err, hid = -1, cid = -1;
+ unsigned char k[32], pad;
+ unsigned long klen = sizeof(k);
+ symmetric_CBC cbc;
+
+ /* https://tools.ietf.org/html/rfc8018#section-6.2.2 */
+
+ if (hmacid == HMAC_WITH_SHA1) hid = find_hash("sha1");
+ if (hmacid == HMAC_WITH_SHA224) hid = find_hash("sha224");
+ if (hmacid == HMAC_WITH_SHA256) hid = find_hash("sha256");
+ if (hmacid == HMAC_WITH_SHA384) hid = find_hash("sha384");
+ if (hmacid == HMAC_WITH_SHA512) hid = find_hash("sha512");
+ if (hid == -1) return CRYPT_INVALID_ARG;
+
+ if (encid == DES_EDE3_CBC) {
+ /* https://tools.ietf.org/html/rfc8018#appendix-B.2.2 */
+ cid = find_cipher("3des");
+ klen = 24;
+ if (klen > sizeof(k) || iv_size != 8 || iv == NULL || cid == -1) goto LBL_ERROR;
+ if ((err = pkcs_5_alg2(pass, pass_size, salt, salt_size, iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_start(cid, iv, k, klen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(enc_data, dec_data, enc_size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ pad = dec_data[enc_size-1];
+ if (pad < 1 || pad > 8) goto LBL_ERROR;
+ *dec_size = enc_size - pad;
+ return CRYPT_OK;
+ }
+
+ if (encid == DES_CBC) {
+ /* https://tools.ietf.org/html/rfc8018#appendix-B.2.1 */
+ cid = find_cipher("des");
+ klen = 8; /* 64 bits */
+ if (klen > sizeof(k) || iv_size != 8 || iv == NULL || cid == -1) goto LBL_ERROR;
+ if ((err = pkcs_5_alg2(pass, pass_size, salt, salt_size, iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_start(cid, iv, k, klen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(enc_data, dec_data, enc_size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ pad = dec_data[enc_size-1];
+ if (pad < 1 || pad > 8) goto LBL_ERROR;
+ *dec_size = enc_size - pad;
+ return CRYPT_OK;
+ }
+
+ if (encid == RC2_CBC) {
+ /* https://tools.ietf.org/html/rfc8018#appendix-B.2.3 */
+ cid = find_cipher("rc2");
+ klen = 4; /* default: 32 bits */
+ if (extra_arg == 160) klen = 5;
+ if (extra_arg == 120) klen = 8;
+ if (extra_arg == 58) klen = 16;
+ if (extra_arg >= 256) klen = extra_arg / 8;
+ if (klen > sizeof(k) || iv_size != 8 || iv == NULL || cid == -1) goto LBL_ERROR;
+ if ((err = pkcs_5_alg2(pass, pass_size, salt, salt_size, iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_start(cid, iv, k, klen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(enc_data, dec_data, enc_size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ pad = dec_data[enc_size-1];
+ if (pad < 1 || pad > 8) goto LBL_ERROR;
+ *dec_size = enc_size - pad;
+ return CRYPT_OK;
+ }
+
+LBL_ERROR:
+ zeromem(k, sizeof(k));
+ return CRYPT_INVALID_ARG;
+}
+
+static int _der_decode_pkcs8_flexi(const unsigned char *in, unsigned long inlen,
+ const void *pwd, unsigned long pwdlen,
+ ltc_asn1_list **decoded_list)
+{
+ unsigned long len = inlen;
+ unsigned long dec_size;
+ unsigned char *dec_data = NULL;
+ ltc_asn1_list *l = NULL;
+ int err;
+
+ *decoded_list = NULL;
+ if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) {
+ /* the following "if" detects whether it is encrypted or not */
+ if (l->type == LTC_ASN1_SEQUENCE &&
+ l->child && l->child->type == LTC_ASN1_SEQUENCE &&
+ l->child->child && l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ l->child->child->next && l->child->child->next->type == LTC_ASN1_SEQUENCE &&
+ l->child->next && l->child->next->type == LTC_ASN1_OCTET_STRING) {
+ ltc_asn1_list *lalgoid = l->child->child;
+ ltc_asn1_list *lalgparam = l->child->child->next;
+ unsigned char *enc_data = l->child->next->data;
+ unsigned long enc_size = l->child->next->size;
+ dec_size = enc_size;
+ if ((dec_data = XMALLOC(dec_size)) == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_DONE;
+ }
+ if (lalgparam->child && lalgparam->child->type == LTC_ASN1_OCTET_STRING &&
+ lalgparam->child->next && lalgparam->child->next->type == LTC_ASN1_INTEGER) {
+ /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC:
+ * 0:d=0 hl=4 l= 329 cons: SEQUENCE
+ * 4:d=1 hl=2 l= 27 cons: SEQUENCE (== *lalg)
+ * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3)
+ * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam)
+ * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt)
+ * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
+ * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
+ */
+ unsigned long iter = mp_get_int(lalgparam->child->next->data);
+ unsigned long salt_size = lalgparam->child->size;
+ unsigned char *salt = lalgparam->child->data;
+ err = _pbes1_decrypt(enc_data, enc_size, pwd, pwdlen, salt, salt_size, iter, lalgoid->data, lalgoid->size, dec_data, &dec_size);
+ if (err != CRYPT_OK) goto LBL_DONE;
+ }
+ else if (PBES2 == _oid_to_id(lalgoid->data, lalgoid->size) &&
+ lalgparam->child && lalgparam->child->type == LTC_ASN1_SEQUENCE &&
+ lalgparam->child->child && lalgparam->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ lalgparam->child->child->next && lalgparam->child->child->next->type == LTC_ASN1_SEQUENCE &&
+ lalgparam->child->next && lalgparam->child->next->type == LTC_ASN1_SEQUENCE &&
+ lalgparam->child->next->child && lalgparam->child->next->child->type == LTC_ASN1_OBJECT_IDENTIFIER) {
+ /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc:
+ * 0:d=0 hl=4 l= 380 cons: SEQUENCE
+ * 4:d=1 hl=2 l= 78 cons: SEQUENCE (== *lalg)
+ * 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13)
+ * 17:d=2 hl=2 l= 65 cons: SEQUENCE (== *lalgparam)
+ * 19:d=3 hl=2 l= 41 cons: SEQUENCE
+ * 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2
+ * 32:d=4 hl=2 l= 28 cons: SEQUENCE
+ * 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== salt)
+ * 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
+ * 48:d=5 hl=2 l= 12 cons: SEQUENCE (this sequence is optional, may be missing)
+ * 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256
+ * 60:d=6 hl=2 l= 0 prim: NULL
+ * 62:d=3 hl=2 l= 20 cons: SEQUENCE
+ * 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc
+ * 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A
+ * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
+ */
+ ltc_asn1_list *lkdf = lalgparam->child->child;
+ ltc_asn1_list *lenc = lalgparam->child->next->child;
+ int kdfid = _oid_to_id(lkdf->data, lkdf->size);
+ int encid = _oid_to_id(lenc->data, lenc->size);
+ if (PBKDF2 == kdfid &&
+ lkdf->next && lkdf->next->type == LTC_ASN1_SEQUENCE &&
+ lkdf->next->child && lkdf->next->child->type == LTC_ASN1_OCTET_STRING &&
+ lkdf->next->child->next && lkdf->next->child->next->type == LTC_ASN1_INTEGER) {
+ unsigned long iter = mp_get_int(lkdf->next->child->next->data);
+ unsigned long salt_size = lkdf->next->child->size;
+ unsigned char *salt = lkdf->next->child->data;
+ unsigned char *iv = NULL;
+ unsigned long iv_size = 0;
+ unsigned long arg = 0;
+ ltc_asn1_list *loptseq = lkdf->next->child->next->next;
+ int hmacid = HMAC_WITH_SHA1; /* this is default */
+ if (loptseq && loptseq->type == LTC_ASN1_SEQUENCE &&
+ loptseq->child && loptseq->child->type == LTC_ASN1_OBJECT_IDENTIFIER) {
+ /* this sequence is optional */
+ hmacid = _oid_to_id(loptseq->child->data, loptseq->child->size);
+ }
+ if (lenc->next && lenc->next->type == LTC_ASN1_OCTET_STRING) {
+ /* DES-CBC + DES_EDE3_CBC */
+ iv = lenc->next->data;
+ iv_size = lenc->next->size;
+ }
+ else if (lenc->next && lenc->next->type == LTC_ASN1_SEQUENCE &&
+ lenc->next->child && lenc->next->child->type == LTC_ASN1_INTEGER &&
+ lenc->next->child->next && lenc->next->child->next->type == LTC_ASN1_OCTET_STRING) {
+ /* RC2-CBC is a bit special */
+ iv = lenc->next->child->next->data;
+ iv_size = lenc->next->child->next->size;
+ arg = mp_get_int(lenc->next->child->data);
+ }
+ err = _pbes2_pbkdf2_decrypt(enc_data, enc_size, pwd, pwdlen, salt, salt_size, iv, iv_size, iter, hmacid, encid, arg, dec_data, &dec_size);
+ if (err != CRYPT_OK) goto LBL_DONE;
+ }
+ else {
+ /* non-PBKDF2 algorithms are not supported */
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+ }
+ }
+ else {
+ /* unsupported encryption */
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+ }
+ der_free_sequence_flexi(l);
+ l = NULL;
+ err = der_decode_sequence_flexi(dec_data, &dec_size, &l);
+ if (err != CRYPT_OK) goto LBL_DONE;
+ *decoded_list = l;
+ }
+ else {
+ /* not encrypted */
+ err = CRYPT_OK;
+ *decoded_list = l;
+ }
+ }
+
+LBL_DONE:
+ if (dec_data) XFREE(dec_data);
return err;
+}
+
+/* NOTE: _der_decode_pkcs8_flexi & related stuff can be shared with rsa_import_pkcs8() */
-LBL_ERR:
- mp_clear_multi(prime, order, a, b, gx, gy, NULL);
-LBL_NOCLEAR:
- XFREE(buf2);
-LBL_FREE:
- XFREE(buf1);
-LBL_NOFREE:
+int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const void *pwd, unsigned long pwdlen,
+ ecc_key *key)
+{
+ void *a, *b, *gx, *gy;
+ unsigned long len, cofactor;
+ oid_st ecoid;
+ int err;
+ ltc_asn1_list *p = NULL, *l = NULL;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* get EC alg oid */
+ err = pk_get_oid(PKA_EC, &ecoid);
+ if (err != CRYPT_OK) return err;
+
+ /* init key */
+ err = mp_init_multi(&a, &b, &gx, &gy, NULL);
+ if (err != CRYPT_OK) return err;
+
+ if ((err = _der_decode_pkcs8_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) {
+ if (l->type == LTC_ASN1_SEQUENCE &&
+ l->child && l->child->type == LTC_ASN1_INTEGER &&
+ l->child->next && l->child->next->type == LTC_ASN1_SEQUENCE &&
+ l->child->next->child && l->child->next->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ l->child->next->next && l->child->next->next->type == LTC_ASN1_OCTET_STRING) {
+ ltc_asn1_list *lseq = l->child->next;
+ ltc_asn1_list *lpri = l->child->next->next;
+ ltc_asn1_list *lecoid = l->child->next->child;
+
+ if ((lecoid->size != ecoid.OIDlen) ||
+ XMEMCMP(ecoid.OID, lecoid->data, ecoid.OIDlen * sizeof(ecoid.OID[0]))) {
+ err = CRYPT_PK_INVALID_TYPE;
+ goto LBL_DONE;
+ }
+
+ if (lseq->child->next && lseq->child->next->type == LTC_ASN1_OBJECT_IDENTIFIER) {
+ /* CASE 1: curve by OID (AKA short variant):
+ * 0:d=0 hl=2 l= 100 cons: SEQUENCE
+ * 2:d=1 hl=2 l= 1 prim: INTEGER :00
+ * 5:d=1 hl=2 l= 16 cons: SEQUENCE (== *lseq)
+ * 7:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
+ * 16:d=2 hl=2 l= 5 prim: OBJECT :secp256k1 (== 1.3.132.0.10)
+ * 23:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== privatekey)
+ */
+ ltc_asn1_list *loid = lseq->child->next;
+ if ((err = ecc_set_dp_oid(loid->data, loid->size, key)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ }
+ else if (lseq->child->next && lseq->child->next->type == LTC_ASN1_SEQUENCE) {
+ /* CASE 2: explicit curve parameters (AKA long variant):
+ * 0:d=0 hl=3 l= 227 cons: SEQUENCE
+ * 3:d=1 hl=2 l= 1 prim: INTEGER :00
+ * 6:d=1 hl=3 l= 142 cons: SEQUENCE (== *lseq)
+ * 9:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
+ * 18:d=2 hl=3 l= 130 cons: SEQUENCE (== *lcurve)
+ * 21:d=3 hl=2 l= 1 prim: INTEGER :01
+ * 24:d=3 hl=2 l= 44 cons: SEQUENCE (== *lfield)
+ * 26:d=4 hl=2 l= 7 prim: OBJECT :prime-field
+ * 35:d=4 hl=2 l= 33 prim: INTEGER :(== curve.prime)
+ * 70:d=3 hl=2 l= 6 cons: SEQUENCE (== *lpoint)
+ * 72:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.A)
+ * 75:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.B)
+ * 78:d=3 hl=2 l= 33 prim: OCTET STRING :bytes (== curve.G-point)
+ * 113:d=3 hl=2 l= 33 prim: INTEGER :(== curve.order)
+ * 148:d=3 hl=2 l= 1 prim: INTEGER :(== curve.cofactor)
+ * 151:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== privatekey)
+ */
+ ltc_asn1_list *lcurve = lseq->child->next;
+
+ if (lcurve->child && lcurve->child->type == LTC_ASN1_INTEGER &&
+ lcurve->child->next && lcurve->child->next->type == LTC_ASN1_SEQUENCE &&
+ lcurve->child->next->next && lcurve->child->next->next->type == LTC_ASN1_SEQUENCE &&
+ lcurve->child->next->next->next && lcurve->child->next->next->next->type == LTC_ASN1_OCTET_STRING &&
+ lcurve->child->next->next->next->next && lcurve->child->next->next->next->next->type == LTC_ASN1_INTEGER &&
+ lcurve->child->next->next->next->next->next && lcurve->child->next->next->next->next->next->type == LTC_ASN1_INTEGER) {
+
+ ltc_asn1_list *lfield = lcurve->child->next;
+ ltc_asn1_list *lpoint = lcurve->child->next->next;
+ ltc_asn1_list *lg = lcurve->child->next->next->next;
+ ltc_asn1_list *lorder = lcurve->child->next->next->next->next;
+ cofactor = mp_get_int(lcurve->child->next->next->next->next->next->data);
+
+ if (lfield->child && lfield->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ lfield->child->next && lfield->child->next->type == LTC_ASN1_INTEGER &&
+ lpoint->child && lpoint->child->type == LTC_ASN1_OCTET_STRING &&
+ lpoint->child->next && lpoint->child->next->type == LTC_ASN1_OCTET_STRING) {
+
+ ltc_asn1_list *lprime = lfield->child->next;
+ if ((err = mp_read_unsigned_bin(a, lpoint->child->data, lpoint->child->size)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = mp_read_unsigned_bin(b, lpoint->child->next->data, lpoint->child->next->size)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = ltc_ecc_import_point(lg->data, lg->size, lprime->data, a, b, gx, gy)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = ecc_set_dp_bn(a, b, lprime->data, lorder->data, gx, gy, cofactor, key)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ }
+ }
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+ }
+
+ /* load private key value 'k' */
+ len = lpri->size;
+ if ((err = der_decode_sequence_flexi(lpri->data, &len, &p)) == CRYPT_OK) {
+ err = CRYPT_INVALID_PACKET;
+ if (p->type == LTC_ASN1_SEQUENCE &&
+ p->child && p->child->type == LTC_ASN1_INTEGER &&
+ p->child->next && p->child->next->type == LTC_ASN1_OCTET_STRING) {
+ ltc_asn1_list *lk = p->child->next;
+ if (mp_cmp_d(p->child->data, 1) != LTC_MP_EQ) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ECCFREE;
+ }
+ if ((err = ecc_set_key(lk->data, lk->size, PK_PRIVATE, key)) != CRYPT_OK) {
+ goto LBL_ECCFREE;
+ }
+ goto LBL_DONE; /* success */
+ }
+ }
+ }
+ }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+
+LBL_ECCFREE:
+ ecc_free(key);
+LBL_DONE:
+ mp_clear_multi(a, b, gx, gy, NULL);
+ if (l) der_free_sequence_flexi(l);
+ if (p) der_free_sequence_flexi(p);
return err;
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_import_raw.c b/src/ltc/pk/ecc/ecc_import_raw.c
deleted file mode 100644
index 1ea4bb1e..00000000
--- a/src/ltc/pk/ecc/ecc_import_raw.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* 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.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-/** Import raw public or private key (public keys = ANSI X9.63 compressed or uncompressed; private keys = raw bytes)
- @param in The input data to read
- @param inlen The length of the input data
- @param key [out] destination to store imported key
- @param dp Curve parameters
- Return CRYPT_OK on success
-*/
-
-int ecc_import_raw(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp)
-{
- int err, type = -1;
- unsigned long size = 0;
- void *prime, *a, *b;
- ecc_point *base;
-
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(key != NULL);
- LTC_ARGCHK(dp != NULL);
-
- /* init key + temporary numbers */
- if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &a, &b, NULL) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
- if (inlen <= (unsigned long)dp->size) {
- /* read PRIVATE key */
- type = PK_PRIVATE;
- size = inlen;
- /* load private k */
- if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, size)) != CRYPT_OK) {
- goto cleanup;
- }
- if (mp_iszero(key->k)) {
- err = CRYPT_INVALID_PACKET;
- goto cleanup;
- }
- /* init base point */
- if ((base = ltc_ecc_new_point()) == NULL) {
- err = CRYPT_MEM;
- goto cleanup;
- }
- /* load prime + base point */
- if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_read_radix(base->x, dp->Gx, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_read_radix(base->y, dp->Gy, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto cleanup; }
- /* make the public key */
- if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto cleanup; }
- /* cleanup */
- ltc_ecc_del_point(base);
- }
- else {
- /* read PUBLIC key */
- type = PK_PUBLIC;
- /* load prime + A + B */
- if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) { goto cleanup; }
- err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y);
- if (err != CRYPT_OK) { goto cleanup; }
- if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto cleanup; }
- }
-
- if ((err = ltc_ecc_is_point(dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) {
- err = CRYPT_INVALID_PACKET;
- goto cleanup;
- }
-
- key->type = type;
- key->idx = -1;
- key->dp = dp;
-
- /* we're done */
- mp_clear_multi(prime, a, b, NULL);
- return CRYPT_OK;
-cleanup:
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, prime, a, b, NULL);
- return err;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_import_x509.c b/src/ltc/pk/ecc/ecc_import_x509.c
new file mode 100644
index 00000000..e57b156f
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_import_x509.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+/**
+ Import an ECC key from a X.509 certificate
+ @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 ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ int err;
+ unsigned long len;
+ ltc_asn1_list *decoded_list = NULL, *l;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ len = inlen;
+ if ((err = der_decode_sequence_flexi(in, &len, &decoded_list)) == CRYPT_OK) {
+ l = decoded_list;
+ if (l->type == LTC_ASN1_SEQUENCE &&
+ l->child && l->child->type == LTC_ASN1_SEQUENCE) {
+ err = CRYPT_ERROR;
+ l = l->child->child;
+ while (l) {
+ if (l->type == LTC_ASN1_SEQUENCE && l->data &&
+ l->child && l->child->type == LTC_ASN1_SEQUENCE &&
+ l->child->child && l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ l->child->next && l->child->next->type == LTC_ASN1_BIT_STRING) {
+ err = ecc_import_openssl(l->data, l->size, key);
+ goto LBL_DONE;
+ }
+ l = l->next;
+ }
+ }
+ }
+
+LBL_DONE:
+ if (decoded_list) der_free_sequence_flexi(decoded_list);
+ return err;
+}
+
+#endif /* LTC_MECC */
+
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_make_key.c b/src/ltc/pk/ecc/ecc_make_key.c
index 0d89552e..4617befb 100644
--- a/src/ltc/pk/ecc/ecc_make_key.c
+++ b/src/ltc/pk/ecc/ecc_make_key.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -29,76 +26,34 @@
*/
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
{
- /* BEWARE: Here we are looking up the curve params by keysize (neither curve name nor curve oid),
- * which might be ambiguous (there can more than one curve for given keysize).
- * Thus the chosen curve depends on order of items in ltc_ecc_sets[] - see ecc.c file.
- */
- int x, err;
+ int err;
- /* find key size */
- for (x = 0; (keysize > ltc_ecc_sets[x].size) && (ltc_ecc_sets[x].size != 0); x++);
- keysize = ltc_ecc_sets[x].size;
-
- if (keysize > ECC_MAXSIZE || ltc_ecc_sets[x].size == 0) {
- return CRYPT_INVALID_KEYSIZE;
- }
- err = ecc_make_key_ex(prng, wprng, key, &ltc_ecc_sets[x]);
- key->idx = x;
- return err;
+ if ((err = ecc_set_dp_size(keysize, key)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
+ return CRYPT_OK;
}
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp)
{
+ int err;
+ if ((err = ecc_set_dp(dp, key)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
+ return CRYPT_OK;
+}
+
+int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key)
+{
int err;
- ecc_point *base;
- void *prime, *order, *a;
- unsigned char *buf;
- int keysize, orderbits;
- LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
- LTC_ARGCHK(dp != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(key->dp.size > 0);
/* good prng? */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
- key->idx = -1;
- key->dp = dp;
- keysize = dp->size;
-
- /* 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 ERR_BUF;
- }
-
- /* setup the key variables */
- if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, &a, NULL)) != CRYPT_OK) {
- goto ERR_BUF;
- }
- base = ltc_ecc_new_point();
- if (base == NULL) {
- err = CRYPT_MEM;
- goto errkey;
- }
-
- /* read in the specs for this key */
- if ((err = mp_read_radix(prime, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_read_radix(order, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_read_radix(base->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_read_radix(base->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != CRYPT_OK) { goto errkey; }
-
/* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates):
* the generated private key k should be the range [1, order-1]
* a/ N = bitlen(order)
@@ -106,29 +61,23 @@ int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set
* c/ if k not in [1, order-1] go to b/
* e/ Q = k*G
*/
- orderbits = mp_count_bits(order);
- do {
- if ((err = rand_bn_bits(key->k, orderbits, prng, wprng)) != CRYPT_OK) { goto errkey; }
- } while (mp_iszero(key->k) || mp_cmp(key->k, order) != LTC_MP_LT);
+ if ((err = rand_bn_upto(key->k, key->dp.order, prng, wprng)) != CRYPT_OK) {
+ goto error;
+ }
/* make the public key */
- if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto errkey; }
+ if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) {
+ goto error;
+ }
key->type = PK_PRIVATE;
- /* free up ram */
+ /* success */
err = CRYPT_OK;
goto cleanup;
-errkey:
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+
+error:
+ ecc_free(key);
cleanup:
- ltc_ecc_del_point(base);
- mp_clear_multi(prime, order, a, NULL);
-ERR_BUF:
-#ifdef LTC_CLEAN_STACK
- zeromem(buf, ECC_MAXSIZE);
-#endif
- XFREE(buf);
return err;
}
diff --git a/src/ltc/pk/ecc/ecc_set_dp.c b/src/ltc/pk/ecc/ecc_set_dp.c
new file mode 100644
index 00000000..17a0d2aa
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_set_dp.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.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+int ecc_set_dp(const ltc_ecc_set_type *set, ecc_key *key)
+{
+ unsigned long i;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(set != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_read_radix(key->dp.prime, set->prime, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.order, set->order, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.A, set->A, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.B, set->B, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.base.x, set->Gx, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.base.y, set->Gy, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = set->cofactor;
+ key->dp.size = mp_unsigned_bin_size(key->dp.prime);
+ /* OID */
+ key->dp.oidlen = set->oidlen;
+ for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = set->oid[i];
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+int ecc_set_dp_size(int size, ecc_key *key)
+{
+ const ltc_ecc_set_type *dp = NULL;
+ int err;
+
+ /* for compatibility with libtomcrypt-1.17 the sizes below must match the specific curves */
+ if (size <= 14) {
+ if ((err = ecc_get_set_by_name("SECP112R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 16) {
+ if ((err = ecc_get_set_by_name("SECP128R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 20) {
+ if ((err = ecc_get_set_by_name("SECP160R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 24) {
+ if ((err = ecc_get_set_by_name("SECP192R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 28) {
+ if ((err = ecc_get_set_by_name("SECP224R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 32) {
+ if ((err = ecc_get_set_by_name("SECP256R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 48) {
+ if ((err = ecc_get_set_by_name("SECP384R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 66) {
+ if ((err = ecc_get_set_by_name("SECP521R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+
+ return CRYPT_INVALID_ARG;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_set_dp_internal.c b/src/ltc/pk/ecc/ecc_set_dp_internal.c
new file mode 100644
index 00000000..bd7c0403
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_set_dp_internal.c
@@ -0,0 +1,150 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+static void _ecc_oid_lookup(ecc_key *key)
+{
+ int err;
+ unsigned i;
+ void *tmp;
+ const ltc_ecc_set_type *set;
+
+ key->dp.oidlen = 0;
+ if ((err = mp_init(&tmp)) != CRYPT_OK) return;
+ for (set = ltc_ecc_sets; set->name != NULL; set++) {
+ if ((err = mp_read_radix(tmp, set->prime, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.prime) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->order, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.order) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->A, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.A) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->B, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.B) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->Gx, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.base.x) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->Gy, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.base.y) != LTC_MP_EQ)) continue;
+ if (key->dp.cofactor != set->cofactor) continue;
+ break; /* found */
+ }
+ mp_clear(tmp);
+ if (set->name != NULL) {
+ /* OID found */
+ key->dp.oidlen = set->oidlen;
+ for(i = 0; i < set->oidlen; i++) key->dp.oid[i] = set->oid[i];
+ }
+}
+
+int ecc_set_dp_oid(unsigned long *oid, unsigned long oidsize, ecc_key *key)
+{
+ int i;
+
+ LTC_ARGCHK(oid != NULL);
+ LTC_ARGCHK(oidsize > 0);
+
+ for(i = 0; ltc_ecc_sets[i].name != NULL; i++) {
+ if ((oidsize == ltc_ecc_sets[i].oidlen) &&
+ (XMEM_NEQ(oid, ltc_ecc_sets[i].oid, sizeof(unsigned long) * ltc_ecc_sets[i].oidlen) == 0)) {
+ break;
+ }
+ }
+ if (ltc_ecc_sets[i].name == NULL) return CRYPT_ERROR; /* not found */
+ return ecc_set_dp(&ltc_ecc_sets[i], key);
+}
+
+int ecc_set_dp_copy(ecc_key *srckey, ecc_key *key)
+{
+ unsigned long i;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(srckey != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_copy(srckey->dp.prime, key->dp.prime )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.order, key->dp.order )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.A, key->dp.A )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.B, key->dp.B )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.base.x, key->dp.base.x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.base.y, key->dp.base.y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.base.z, key->dp.base.z)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = srckey->dp.cofactor;
+ key->dp.size = srckey->dp.size;
+ /* OID */
+ if (srckey->dp.oidlen > 0) {
+ key->dp.oidlen = srckey->dp.oidlen;
+ for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = srckey->dp.oid[i];
+ }
+ else {
+ _ecc_oid_lookup(key); /* try to find OID in ltc_ecc_sets */
+ }
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+int ecc_set_dp_bn(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(prime != NULL);
+ LTC_ARGCHK(order != NULL);
+ LTC_ARGCHK(gx != NULL);
+ LTC_ARGCHK(gy != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_copy(prime, key->dp.prime )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(order, key->dp.order )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(a, key->dp.A )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(b, key->dp.B )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(gx, key->dp.base.x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(gy, key->dp.base.y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = cofactor;
+ key->dp.size = mp_unsigned_bin_size(prime);
+ /* try to find OID in ltc_ecc_sets */
+ _ecc_oid_lookup(key);
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_set_key.c b/src/ltc/pk/ecc/ecc_set_key.c
new file mode 100644
index 00000000..9fabcf2e
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_set_key.c
@@ -0,0 +1,67 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key)
+{
+ int err;
+ void *prime, *a, *b;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+
+ prime = key->dp.prime;
+ a = key->dp.A;
+ b = key->dp.B;
+
+ if (type == PK_PRIVATE && inlen <= (unsigned long)key->dp.size) {
+ /* load private key */
+ if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, inlen)) != CRYPT_OK) {
+ goto error;
+ }
+ if (mp_iszero(key->k)) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ /* compute public key */
+ if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto error; }
+ key->type = type;
+ }
+ else if (type == PK_PUBLIC) {
+ /* load public key */
+ if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
+ key->type = type;
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* point on the curve + other checks */
+ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_shared_secret.c b/src/ltc/pk/ecc/ecc_shared_secret.c
index d21d45cf..92917cc1 100644
--- a/src/ltc/pk/ecc/ecc_shared_secret.c
+++ b/src/ltc/pk/ecc/ecc_shared_secret.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -45,29 +42,16 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
return CRYPT_PK_NOT_PRIVATE;
}
- if (ltc_ecc_is_valid_idx(private_key->idx) == 0 || ltc_ecc_is_valid_idx(public_key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
-
-/* XXX FIXME names can be different in some situations
- if (XSTRCMP(private_key->dp->name, public_key->dp->name) != 0) {
- return CRYPT_PK_TYPE_MISMATCH;
- }
-*/
/* make new point */
result = ltc_ecc_new_point();
if (result == NULL) {
return CRYPT_MEM;
}
- if ((err = mp_init_multi(&prime, &a, NULL)) != CRYPT_OK) {
- ltc_ecc_del_point(result);
- return err;
- }
+ prime = private_key->dp.prime;
+ a = private_key->dp.A;
- if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK) { goto done; }
- if ((err = mp_read_radix(a, (char *)private_key->dp->A, 16)) != CRYPT_OK) { goto done; }
- if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; }
x = (unsigned long)mp_unsigned_bin_size(prime);
if (*outlen < x) {
@@ -76,12 +60,11 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
goto done;
}
zeromem(out, x);
- if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; }
+ if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; }
err = CRYPT_OK;
*outlen = x;
done:
- mp_clear_multi(prime, a, NULL);
ltc_ecc_del_point(result);
return err;
}
diff --git a/src/ltc/pk/ecc/ecc_sign_hash.c b/src/ltc/pk/ecc/ecc_sign_hash.c
index 7f0a4e47..87e95060 100644
--- a/src/ltc/pk/ecc/ecc_sign_hash.c
+++ b/src/ltc/pk/ecc/ecc_sign_hash.c
@@ -7,10 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
#include "tomcrypt.h"
#ifdef LTC_MECC
@@ -20,13 +16,13 @@
ECC Crypto, Tom St Denis
*/
-static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long *outlen,
- prng_state *prng, int wprng, ecc_key *key, int sigformat)
+static 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, int sigformat)
{
ecc_key pubkey;
void *r, *s, *e, *p;
- int err;
+ int err, max_iterations = LTC_PK_MAX_RETRIES;
unsigned long pbits, pbytes, i, shift_right;
unsigned char ch, buf[MAXBLOCKSIZE];
@@ -40,22 +36,17 @@ static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
return CRYPT_PK_NOT_PRIVATE;
}
- /* is the IDX valid ? */
- if (ltc_ecc_is_valid_idx(key->idx) != 1) {
- return CRYPT_PK_INVALID_TYPE;
- }
-
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* init the bignums */
- if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) {
+ if ((err = mp_init_multi(&r, &s, &e, NULL)) != CRYPT_OK) {
return err;
}
- if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; }
/* get the hash and load it as a bignum into 'e' */
+ p = key->dp.order;
pbits = mp_count_bits(p);
pbytes = (pbits+7) >> 3;
if (pbits > inlen*8) {
@@ -75,16 +66,16 @@ static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
}
/* make up a key and export the public copy */
- for (;;) {
- if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) { goto errnokey; }
+ do {
+ if ((err = ecc_set_dp_copy(key, &pubkey)) != CRYPT_OK) { goto errnokey; }
+ if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; }
/* find r = x1 mod n */
- if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
if (mp_iszero(r) == LTC_MP_YES) {
ecc_free(&pubkey);
- }
- else {
+ } else {
/* find s = (e + xr)/k */
if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/k */
if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */
@@ -96,6 +87,10 @@ static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
break;
}
}
+ } while (--max_iterations > 0);
+
+ if (max_iterations == 0) {
+ goto errnokey;
}
if (sigformat == 1) {
@@ -120,7 +115,7 @@ static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
error:
ecc_free(&pubkey);
errnokey:
- mp_clear_multi(r, s, p, e, NULL);
+ mp_clear_multi(r, s, e, NULL);
return err;
}
@@ -139,7 +134,7 @@ 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)
{
- return ecc_sign_hash_ex(in, inlen, out, outlen, prng, wprng, key, 0);
+ return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 0);
}
/**
@@ -157,7 +152,11 @@ int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, ecc_key *key)
{
- return ecc_sign_hash_ex(in, inlen, out, outlen, prng, wprng, key, 1);
+ return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 1);
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_sizes.c b/src/ltc/pk/ecc/ecc_sizes.c
index 8f61d5fd..dcd310c8 100644
--- a/src/ltc/pk/ecc/ecc_sizes.c
+++ b/src/ltc/pk/ecc/ecc_sizes.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -21,20 +18,25 @@
void ecc_sizes(int *low, int *high)
{
- int i;
- LTC_ARGCHKVD(low != NULL);
- LTC_ARGCHKVD(high != NULL);
-
- *low = INT_MAX;
- *high = 0;
- for (i = 0; ltc_ecc_sets[i].size != 0; i++) {
- if (ltc_ecc_sets[i].size < *low) {
- *low = ltc_ecc_sets[i].size;
- }
- if (ltc_ecc_sets[i].size > *high) {
- *high = ltc_ecc_sets[i].size;
- }
- }
+ int i, size;
+ void *prime;
+
+ LTC_ARGCHKVD(low != NULL);
+ LTC_ARGCHKVD(high != NULL);
+
+ *low = INT_MAX;
+ *high = 0;
+
+ if (mp_init(&prime) == CRYPT_OK) {
+ for (i = 0; ltc_ecc_sets[i].name != NULL; i++) {
+ if (mp_read_radix(prime, ltc_ecc_sets[i].prime, 16) == CRYPT_OK) {
+ size = mp_unsigned_bin_size(prime);
+ if (size < *low) *low = size;
+ if (size > *high) *high = size;
+ }
+ }
+ mp_clear(prime);
+ }
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_verify_hash.c b/src/ltc/pk/ecc/ecc_verify_hash.c
index f9165603..34a49041 100644
--- a/src/ltc/pk/ecc/ecc_verify_hash.c
+++ b/src/ltc/pk/ecc/ecc_verify_hash.c
@@ -7,10 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
#include "tomcrypt.h"
#ifdef LTC_MECC
@@ -20,13 +16,13 @@
ECC Crypto, Tom St Denis
*/
-static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
- const unsigned char *hash, unsigned long hashlen,
- int *stat, ecc_key *key, int sigformat)
+static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key, int sigformat)
{
- ecc_point *mG, *mQ;
- void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *mu, *ma;
- void *mp;
+ ecc_point *mG = NULL, *mQ = NULL;
+ void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3 = NULL, *mu = NULL, *ma = NULL;
+ void *mp = NULL;
int err;
unsigned long pbits, pbytes, i, shift_right;
unsigned char ch, buf[MAXBLOCKSIZE];
@@ -38,18 +34,19 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
/* default to invalid signature */
*stat = 0;
- mp = NULL;
-
- /* is the IDX valid ? */
- if (ltc_ecc_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, &a, &mu, &ma, NULL)) != CRYPT_OK) {
+ if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, NULL)) != CRYPT_OK) {
return CRYPT_MEM;
}
+ p = key->dp.order;
+ m = key->dp.prime;
+ a = key->dp.A;
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) {
+ goto error;
+ }
+
/* allocate points */
mG = ltc_ecc_new_point();
mQ = ltc_ecc_new_point();
@@ -70,23 +67,15 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
}
else {
/* ASN.1 format */
- if ((err = der_decode_sequence_multi(sig, siglen,
+ if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
LTC_ASN1_INTEGER, 1UL, r,
LTC_ASN1_INTEGER, 1UL, s,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; }
}
- /* get the order */
- if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto error; }
-
- /* get the modulus */
- if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto error; }
-
- /* get the a */
- if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK) { goto error; }
-
/* check for zero */
- if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
+ if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT ||
+ mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
err = CRYPT_INVALID_PACKET;
goto error;
}
@@ -120,24 +109,28 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
/* find mG and mQ */
- if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto error; }
- if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto error; }
- if ((err = mp_set(mG->z, 1)) != CRYPT_OK) { goto error; }
-
+ if ((err = mp_copy(key->dp.base.x, mG->x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(key->dp.base.y, mG->y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(key->dp.base.z, mG->z)) != CRYPT_OK) { goto error; }
if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK) { goto error; }
if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK) { goto error; }
if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK) { goto error; }
+ /* find the montgomery mp */
+ if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if (mp_cmp(a_plus3, m) != LTC_MP_EQ) {
+ if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; }
+ }
+
/* compute u1*mG + u2*mQ = mG */
if (ltc_mp.ecc_mul2add == NULL) {
if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; }
if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; }
- /* find the montgomery mp */
- if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
- if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; }
- if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; }
-
/* add them */
if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; }
@@ -145,7 +138,7 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
} else {
/* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
- if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, a, m)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; }
}
/* v = X_x1 mod n */
@@ -159,9 +152,11 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
/* clear up and return */
err = CRYPT_OK;
error:
- ltc_ecc_del_point(mG);
- ltc_ecc_del_point(mQ);
- mp_clear_multi(r, s, v, w, u1, u2, p, e, m, a, mu, ma, NULL);
+ if (mG != NULL) ltc_ecc_del_point(mG);
+ if (mQ != NULL) ltc_ecc_del_point(mQ);
+ if (mu != NULL) mp_clear(mu);
+ if (ma != NULL) mp_clear(ma);
+ mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, NULL);
if (mp != NULL) {
mp_montgomery_free(mp);
}
@@ -182,7 +177,7 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key)
{
- return ecc_verify_hash_ex(sig, siglen, hash, hashlen, stat, key, 0);
+ return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 0);
}
/**
@@ -199,7 +194,11 @@ int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key)
{
- return ecc_verify_hash_ex(sig, siglen, hash, hashlen, stat, key, 1);
+ return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 1);
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_export_point.c b/src/ltc/pk/ecc/ltc_ecc_export_point.c
index 086e4c2e..84750c80 100644
--- a/src/ltc/pk/ecc/ltc_ecc_export_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_export_point.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -62,3 +57,7 @@ int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, voi
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_import_point.c b/src/ltc/pk/ecc/ltc_ecc_import_point.c
index d4d028d5..6c8107c8 100644
--- a/src/ltc/pk/ecc/ltc_ecc_import_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_import_point.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -70,3 +65,7 @@ cleanup:
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_is_point.c b/src/ltc/pk/ecc/ltc_ecc_is_point.c
index 9ea963c5..46e1a6d4 100644
--- a/src/ltc/pk/ecc/ltc_ecc_is_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_is_point.c
@@ -5,10 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
*/
#include "tomcrypt.h"
@@ -22,42 +18,39 @@
@return CRYPT_OK if valid
*/
-int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y)
+int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y)
{
void *prime, *a, *b, *t1, *t2;
int err;
- if ((err = mp_init_multi(&prime, &a, &b, &t1, &t2, NULL)) != CRYPT_OK) {
- return err;
- }
+ prime = dp->prime;
+ b = dp->B;
+ a = dp->A;
- /* load prime, a and b */
- if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) goto cleanup;
- if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) goto cleanup;
- if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) return err;
/* compute y^2 */
- if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup;
/* compute x^3 */
- if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup;
- if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup;
- if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup;
/* compute y^2 - x^3 */
- if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup;
/* compute y^2 - x^3 - a*x */
- if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup;
- if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup;
- if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup;
/* adjust range (0, prime) */
while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
- if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup;
}
while (mp_cmp(t1, prime) != LTC_MP_LT) {
- if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup;
}
/* compare to b */
@@ -68,8 +61,12 @@ int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y)
}
cleanup:
- mp_clear_multi(prime, a, b, t1, t2, NULL);
+ mp_clear_multi(t1, t2, NULL);
return err;
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c b/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c
index d5f0f0b2..87f3b0c3 100644
--- a/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c
+++ b/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c
@@ -15,7 +15,7 @@
* a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0)
*/
-int ltc_ecc_is_point_at_infinity(ecc_point *P, void *modulus)
+int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus)
{
int err, retval = 0;
void *x3, *y2;
@@ -46,3 +46,7 @@ done:
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c b/src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c
deleted file mode 100644
index d14ab330..00000000
--- a/src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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.
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-#include "tomcrypt.h"
-
-/**
- @file ltc_ecc_is_valid_idx.c
- ECC Crypto, Tom St Denis
-*/
-
-#ifdef LTC_MECC
-
-/** Returns whether an ECC idx is valid or not
- @param n The idx number to check
- @return 1 if valid, 0 if not
-*/
-int ltc_ecc_is_valid_idx(int n)
-{
- int x;
-
- for (x = 0; ltc_ecc_sets[x].size != 0; x++);
- /* -1 is a valid index --- indicating that the domain params were supplied by the user */
- if ((n >= -1) && (n < x)) {
- return 1;
- }
- return 0;
-}
-
-#endif
-/* ref: $Format:%D$ */
-/* git commit: $Format:%H$ */
-/* commit time: $Format:%ai$ */
-
diff --git a/src/ltc/pk/ecc/ltc_ecc_map.c b/src/ltc/pk/ecc/ltc_ecc_map.c
index 9dd202f9..92d059d1 100644
--- a/src/ltc/pk/ecc/ltc_ecc_map.c
+++ b/src/ltc/pk/ecc/ltc_ecc_map.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -43,7 +40,7 @@ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp)
}
if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
- return CRYPT_MEM;
+ return err;
}
/* first map z back to normal */
diff --git a/src/ltc/pk/ecc/ltc_ecc_mul2add.c b/src/ltc/pk/ecc/ltc_ecc_mul2add.c
index a9b780df..80ceb863 100644
--- a/src/ltc/pk/ecc/ltc_ecc_mul2add.c
+++ b/src/ltc/pk/ecc/ltc_ecc_mul2add.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -26,22 +23,23 @@
@param kA What to multiple A by
@param B Second point to multiply
@param kB What to multiple B by
- @param C [out] Destination point (can overlap with A or B
+ @param C [out] Destination point (can overlap with A or B)
+ @param ma ECC curve parameter a in montgomery form
@param modulus Modulus for curve
@return CRYPT_OK on success
*/
-int ltc_ecc_mul2add(ecc_point *A, void *kA,
- ecc_point *B, void *kB,
- ecc_point *C,
- void *a,
- void *modulus)
+int ltc_ecc_mul2add(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus)
{
ecc_point *precomp[16];
unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble;
unsigned x, y;
unsigned char *tA, *tB;
int err, first;
- void *mp, *mu, *ma;
+ void *mp, *mu;
/* argchks */
LTC_ARGCHK(A != NULL);
@@ -95,15 +93,12 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
goto ERR_P;
}
- if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) {
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
goto ERR_MP;
}
if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
goto ERR_MU;
}
- if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) {
- goto ERR_MU;
- }
/* copy ones ... */
if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; }
@@ -183,7 +178,7 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
/* clean up */
ERR_MU:
- mp_clear_multi(mu, ma, NULL);
+ mp_clear(mu);
ERR_MP:
mp_montgomery_free(mp);
ERR_P:
diff --git a/src/ltc/pk/ecc/ltc_ecc_mulmod.c b/src/ltc/pk/ecc/ltc_ecc_mulmod.c
index 8b65ebf6..50dedc16 100644
--- a/src/ltc/pk/ecc/ltc_ecc_mulmod.c
+++ b/src/ltc/pk/ecc/ltc_ecc_mulmod.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -32,11 +29,11 @@
@param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
@return CRYPT_OK on success
*/
-int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
+int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
{
ecc_point *tG, *M[8];
int i, j, err;
- void *mu, *mp, *ma;
+ void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL;
ltc_mp_digit buf;
int first, bitbuf, bitcpy, bitcnt, mode, digidx;
@@ -54,22 +51,16 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
}
/* init montgomery reduction */
- if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
- return err;
- }
- if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- return err;
- }
- if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- mp_clear_multi(mu, ma, NULL);
- return err;
- }
- if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- mp_clear_multi(mu, ma, NULL);
- return err;
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) {
+ if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; }
}
/* alloc ram for window temps */
@@ -79,9 +70,8 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
for (j = 0; j < i; j++) {
ltc_ecc_del_point(M[j]);
}
- mp_montgomery_free(mp);
- mp_clear_multi(mu, ma, NULL);
- return CRYPT_MEM;
+ err = CRYPT_MEM;
+ goto error;
}
}
@@ -209,15 +199,15 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
err = CRYPT_OK;
}
done:
- if (mu != NULL) {
- mp_clear(mu);
- }
- mp_clear(ma);
- mp_montgomery_free(mp);
ltc_ecc_del_point(tG);
for (i = 0; i < 8; i++) {
ltc_ecc_del_point(M[i]);
}
+error:
+ if (ma != NULL) mp_clear(ma);
+ if (a_plus3 != NULL) mp_clear(a_plus3);
+ if (mu != NULL) mp_clear(mu);
+ if (mp != NULL) mp_montgomery_free(mp);
return err;
}
diff --git a/src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c b/src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c
index d6f7f1df..068240ae 100644
--- a/src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c
+++ b/src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -31,11 +28,11 @@
@param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
@return CRYPT_OK on success
*/
-int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
+int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
{
ecc_point *tG, *M[3];
int i, j, err;
- void *mu, *mp, *ma;
+ void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL;
ltc_mp_digit buf;
int bitcnt, mode, digidx;
@@ -53,22 +50,16 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
}
/* init montgomery reduction */
- if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
- return err;
- }
- if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- return err;
- }
- if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
- mp_clear(mu);
- mp_montgomery_free(mp);
- return err;
- }
- if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- mp_clear_multi(mu, ma, NULL);
- return err;
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) {
+ if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; }
}
/* alloc ram for window temps */
@@ -156,15 +147,15 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
err = CRYPT_OK;
}
done:
- if (mu != NULL) {
- mp_clear(mu);
- }
- mp_clear(ma);
- mp_montgomery_free(mp);
ltc_ecc_del_point(tG);
for (i = 0; i < 3; i++) {
ltc_ecc_del_point(M[i]);
}
+error:
+ if (ma != NULL) mp_clear(ma);
+ if (a_plus3 != NULL) mp_clear(a_plus3);
+ if (mu != NULL) mp_clear(mu);
+ if (mp != NULL) mp_montgomery_free(mp);
return err;
}
diff --git a/src/ltc/pk/ecc/ltc_ecc_points.c b/src/ltc/pk/ecc/ltc_ecc_points.c
index 416fc909..772e8efd 100644
--- a/src/ltc/pk/ecc/ltc_ecc_points.c
+++ b/src/ltc/pk/ecc/ltc_ecc_points.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
diff --git a/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c b/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c
index 3434902a..0182d0a8 100644
--- a/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -24,12 +21,12 @@
@param P The point to add
@param Q The point to add
@param R [out] The destination of the double
- @param ma ECC curve parameter a in montgomery form (if NULL we assume a == -3)
+ @param ma ECC curve parameter a in montgomery form
@param modulus The modulus of the field the ECC curve is in
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
-int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp)
+int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp)
{
void *t1, *t2, *x, *y, *z;
int err;
diff --git a/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c b/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c
index cc01b233..57cfd6fd 100644
--- a/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/* ### Point doubling in Jacobian coordinate system ###
@@ -41,12 +38,12 @@
Double an ECC point
@param P The point to double
@param R [out] The destination of the double
- @param ma ECC curve parameter a in montgomery form (if NULL we assume a == -3)
+ @param ma ECC curve parameter a in montgomery form
@param modulus The modulus of the field the ECC curve is in
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
-int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp)
+int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp)
{
void *t1, *t2;
int err;
@@ -86,7 +83,7 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *ma, void *mod
if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; }
}
- if (ma == NULL) { /* special case for ma == -3 (slightly faster than general case) */
+ if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */
/* T2 = X - T1 */
if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; }
if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
@@ -188,7 +185,7 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *ma, void *mod
err = CRYPT_OK;
done:
- mp_clear_multi(t1, t2, NULL);
+ mp_clear_multi(t2, t1, NULL);
return err;
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_verify_key.c b/src/ltc/pk/ecc/ltc_ecc_verify_key.c
index 0ca1914f..b417465b 100644
--- a/src/ltc/pk/ecc/ecc_verify_key.c
+++ b/src/ltc/pk/ecc/ltc_ecc_verify_key.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -24,7 +19,7 @@
@return CRYPT_OK if successful
*/
-int ecc_verify_key(ecc_key *key)
+int ltc_ecc_verify_key(ecc_key *key)
{
int err;
void *prime = NULL;
@@ -32,18 +27,17 @@ int ecc_verify_key(ecc_key *key)
void *a = NULL;
ecc_point *point;
- if (mp_init_multi(&order, &prime, NULL) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
- /* Test 1: Are the x amd y points of the public key in the field? */
- if ((err = ltc_mp.read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto done2; }
+ prime = key->dp.prime;
+ order = key->dp.order;
+ a = key->dp.A;
+ /* Test 1: Are the x and y points of the public key in the field? */
if (ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) {
if ((ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) ||
(ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) ||
- (ltc_mp.compare_d(key->pubkey.x, 0) != LTC_MP_GT) ||
- (ltc_mp.compare_d(key->pubkey.y, 0) != LTC_MP_GT)
+ (ltc_mp.compare_d(key->pubkey.x, 0) == LTC_MP_LT) ||
+ (ltc_mp.compare_d(key->pubkey.y, 0) == LTC_MP_LT) ||
+ (mp_iszero(key->pubkey.x) && mp_iszero(key->pubkey.y))
)
{
err = CRYPT_INVALID_PACKET;
@@ -52,12 +46,10 @@ int ecc_verify_key(ecc_key *key)
}
/* Test 2: is the public key on the curve? */
- if ((err = ltc_ecc_is_point(key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; }
+ if ((err = ltc_ecc_is_point(&key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; }
/* Test 3: does nG = O? (n = order, O = point at infinity, G = public key) */
point = ltc_ecc_new_point();
- if ((err = ltc_mp.read_radix(order, key->dp->order, 16)) != CRYPT_OK) { goto done1; }
- if ((err = ltc_mp.read_radix(a, key->dp->A, 16)) != CRYPT_OK) { goto done1; }
if ((err = ltc_ecc_mulmod(order, &(key->pubkey), point, a, prime, 1)) != CRYPT_OK) { goto done1; }
if (ltc_ecc_is_point_at_infinity(point, prime)) {
@@ -70,8 +62,11 @@ int ecc_verify_key(ecc_key *key)
done1:
ltc_ecc_del_point(point);
done2:
- mp_clear_multi(prime, order, NULL);
return err;
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/rsa/rsa_export.c b/src/ltc/pk/rsa/rsa_export.c
index a9885de8..b156a83f 100644
--- a/src/ltc/pk/rsa/rsa_export.c
+++ b/src/ltc/pk/rsa/rsa_export.c
@@ -79,7 +79,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key
goto finish;
}
- err = der_encode_subject_public_key_info(out, outlen,
+ err = x509_encode_subject_public_key_info(out, outlen,
PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
finish:
diff --git a/src/ltc/pk/rsa/rsa_import.c b/src/ltc/pk/rsa/rsa_import.c
index 84cd6f65..85771783 100644
--- a/src/ltc/pk/rsa/rsa_import.c
+++ b/src/ltc/pk/rsa/rsa_import.c
@@ -27,7 +27,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
int err;
void *zero;
unsigned char *tmpbuf=NULL;
- unsigned long tmpbuf_len;
+ unsigned long tmpbuf_len, len;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
@@ -47,9 +47,10 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
goto LBL_ERR;
}
- err = der_decode_subject_public_key_info(in, inlen,
+ len = 0;
+ err = x509_decode_subject_public_key_info(in, inlen,
PKA_RSA, tmpbuf, &tmpbuf_len,
- LTC_ASN1_NULL, NULL, 0);
+ LTC_ASN1_NULL, NULL, &len);
if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
diff --git a/src/ltc/pk/rsa/rsa_import_x509.c b/src/ltc/pk/rsa/rsa_import_x509.c
index 0f2d5f1c..aa35e644 100644
--- a/src/ltc/pk/rsa/rsa_import_x509.c
+++ b/src/ltc/pk/rsa/rsa_import_x509.c
@@ -26,7 +26,7 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
{
int err;
unsigned char *tmpbuf;
- unsigned long tmpbuf_len, tmp_inlen;
+ unsigned long tmpbuf_len, tmp_inlen, len;
ltc_asn1_list *decoded_list = NULL, *l;
LTC_ARGCHK(in != NULL);
@@ -77,9 +77,10 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
l->child->type == LTC_ASN1_SEQUENCE && l->child->child &&
l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER && l->child->next &&
l->child->next->type == LTC_ASN1_BIT_STRING) {
- err = der_decode_subject_public_key_info(l->data, l->size,
+ len = 0;
+ err = x509_decode_subject_public_key_info(l->data, l->size,
PKA_RSA, tmpbuf, &tmpbuf_len,
- LTC_ASN1_NULL, NULL, 0);
+ LTC_ASN1_NULL, NULL, &len);
if (err == CRYPT_OK) {
/* now it should be SEQUENCE { INTEGER, INTEGER } */
if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
diff --git a/src/ltc/pk/rsa/rsa_verify_hash.c b/src/ltc/pk/rsa/rsa_verify_hash.c
index b5846965..361f2378 100644
--- a/src/ltc/pk/rsa/rsa_verify_hash.c
+++ b/src/ltc/pk/rsa/rsa_verify_hash.c
@@ -142,10 +142,10 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
- if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
/* fallback to Legacy:missing NULL */
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1);
- if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
XFREE(out);
goto bail_2;
}