diff options
author | Karel Miko <karel.miko@gmail.com> | 2018-01-26 17:22:49 +0100 |
---|---|---|
committer | Karel Miko <karel.miko@gmail.com> | 2018-03-06 09:12:05 +0100 |
commit | 203cabae5f2f2f1ceeaa90a7ed046fad9608cdb8 (patch) | |
tree | e41c1260183a0bc81375f3b5ac639899b32eb5c3 /src/ltc | |
parent | 6179e02bcf9851ad031fe4db6fee7c7fedec71aa (diff) |
ECC improvements
Diffstat (limited to 'src/ltc')
115 files changed, 4007 insertions, 2608 deletions
diff --git a/src/ltc/headers/tomcrypt.h b/src/ltc/headers/tomcrypt.h index 9ed77509..40da87c0 100644 --- a/src/ltc/headers/tomcrypt.h +++ b/src/ltc/headers/tomcrypt.h @@ -27,7 +27,7 @@ extern "C" { /* version */ #define CRYPT 0x0118 -#define SCRYPT "1.18.0" +#define SCRYPT "1.18.1-develop" /* max size of either a cipher/hash block or symmetric key [largest of the two] */ #define MAXBLOCKSIZE 144 @@ -67,7 +67,7 @@ enum { CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */ - CRYPT_UNUSED1, /* UNUSED1 */ + CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */ CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */ diff --git a/src/ltc/headers/tomcrypt_custom.h b/src/ltc/headers/tomcrypt_custom.h index 5a218ff3..c7fc4057 100644 --- a/src/ltc/headers/tomcrypt_custom.h +++ b/src/ltc/headers/tomcrypt_custom.h @@ -468,32 +468,39 @@ #ifdef LTC_MECC /* Supported ECC Key Sizes */ #ifndef LTC_NO_CURVES + #define LTC_ECC_BRAINPOOLP160R1 + #define LTC_ECC_BRAINPOOLP160T1 + #define LTC_ECC_BRAINPOOLP192R1 + #define LTC_ECC_BRAINPOOLP192T1 + #define LTC_ECC_BRAINPOOLP224R1 + #define LTC_ECC_BRAINPOOLP224T1 + #define LTC_ECC_BRAINPOOLP256R1 + #define LTC_ECC_BRAINPOOLP256T1 + #define LTC_ECC_BRAINPOOLP320R1 + #define LTC_ECC_BRAINPOOLP320T1 + #define LTC_ECC_BRAINPOOLP384R1 + #define LTC_ECC_BRAINPOOLP384T1 + #define LTC_ECC_BRAINPOOLP512R1 + #define LTC_ECC_BRAINPOOLP512T1 + #define LTC_ECC_PRIME192V2 + #define LTC_ECC_PRIME192V3 + #define LTC_ECC_PRIME239V1 + #define LTC_ECC_PRIME239V2 + #define LTC_ECC_PRIME239V3 #define LTC_ECC_SECP112R1 #define LTC_ECC_SECP112R2 #define LTC_ECC_SECP128R1 #define LTC_ECC_SECP128R2 + #define LTC_ECC_SECP160K1 #define LTC_ECC_SECP160R1 #define LTC_ECC_SECP160R2 - #define LTC_ECC_SECP160K1 - #define LTC_ECC_BRAINPOOLP160R1 - #define LTC_ECC_SECP192R1 - #define LTC_ECC_PRIME192V2 - #define LTC_ECC_PRIME192V3 #define LTC_ECC_SECP192K1 - #define LTC_ECC_BRAINPOOLP192R1 - #define LTC_ECC_SECP224R1 + #define LTC_ECC_SECP192R1 #define LTC_ECC_SECP224K1 - #define LTC_ECC_BRAINPOOLP224R1 - #define LTC_ECC_PRIME239V1 - #define LTC_ECC_PRIME239V2 - #define LTC_ECC_PRIME239V3 - #define LTC_ECC_SECP256R1 + #define LTC_ECC_SECP224R1 #define LTC_ECC_SECP256K1 - #define LTC_ECC_BRAINPOOLP256R1 - #define LTC_ECC_BRAINPOOLP320R1 + #define LTC_ECC_SECP256R1 #define LTC_ECC_SECP384R1 - #define LTC_ECC_BRAINPOOLP384R1 - #define LTC_ECC_BRAINPOOLP512R1 #define LTC_ECC_SECP521R1 /* OLD deprecated (but still working) defines */ #define LTC_ECC112 diff --git a/src/ltc/headers/tomcrypt_math.h b/src/ltc/headers/tomcrypt_math.h index d73bb91d..f0e9699f 100644 --- a/src/ltc/headers/tomcrypt_math.h +++ b/src/ltc/headers/tomcrypt_math.h @@ -374,48 +374,48 @@ typedef struct { @param k The integer to multiply the point by @param G The point to multiply @param R The destination for kG - @param a ECC curve parameter a (if NULL we assume a == -3) + @param a ECC curve parameter a @param modulus The modulus for the field @param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only) @return CRYPT_OK on success */ int (*ecc_ptmul)( void *k, - ecc_point *G, - ecc_point *R, - void *a, - void *modulus, - int map); + const ecc_point *G, + ecc_point *R, + void *a, + void *modulus, + int map); /** ECC GF(p) point addition @param P The first point @param Q The second point @param R The destination of P + Q - @param a ECC curve parameter a (if NULL we assume a == -3) + @param ma The curve parameter "a" in montgomery form @param modulus The modulus @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ - int (*ecc_ptadd)(ecc_point *P, - ecc_point *Q, - ecc_point *R, - void *a, - void *modulus, - void *mp); + int (*ecc_ptadd)(const ecc_point *P, + const ecc_point *Q, + ecc_point *R, + void *ma, + void *modulus, + void *mp); /** ECC GF(p) point double @param P The first point @param R The destination of 2P - @param a ECC curve parameter a (if NULL we assume a == -3) + @param ma The curve parameter "a" in montgomery form @param modulus The modulus @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ - int (*ecc_ptdbl)(ecc_point *P, - ecc_point *R, - void *a, - void *modulus, - void *mp); + int (*ecc_ptdbl)(const ecc_point *P, + ecc_point *R, + void *ma, + void *modulus, + void *mp); /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1) @@ -435,14 +435,15 @@ typedef struct { @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 ma The curve parameter "a" in montgomery form @param modulus Modulus for curve @return CRYPT_OK on success */ - int (*ecc_mul2add)(ecc_point *A, void *kA, - ecc_point *B, void *kB, - ecc_point *C, - void *a, - void *modulus); + int (*ecc_mul2add)(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus); /* ---- (optional) rsa optimized math (for internal CRT) ---- */ diff --git a/src/ltc/headers/tomcrypt_pk.h b/src/ltc/headers/tomcrypt_pk.h index d12308c0..ac4353ca 100644 --- a/src/ltc/headers/tomcrypt_pk.h +++ b/src/ltc/headers/tomcrypt_pk.h @@ -32,17 +32,17 @@ enum public_key_algorithms { PKA_RSA, PKA_DSA, PKA_EC, - EC_PRIME_FIELD + PKA_EC_PRIMEF }; -#endif /* LTC_SOURCE */ typedef struct Oid { unsigned long OID[16]; - /** Length of DER encoding */ + /** Number of OID digits in use */ unsigned long OIDlen; } oid_st; int pk_get_oid(int pk, oid_st *st); +#endif /* LTC_SOURCE */ /* ---- RSA ---- */ #ifdef LTC_MRSA @@ -254,37 +254,35 @@ int dh_check_pubkey(dh_key *key); /* max private key size */ #define ECC_MAXSIZE 66 -/** Structure defines a NIST GF(p) curve */ +/** Structure defines a GF(p) curve */ typedef struct { - /** The size of the curve in octets */ - int size; - /** name of curve */ - char *name; + const char *name; /** The prime that defines the field the curve is in (encoded in hex) */ - char *prime; + const char *prime; /** The fields A param (hex) */ - char *A; + const char *A; /** The fields B param (hex) */ - char *B; + const char *B; /** The order of the curve (hex) */ - char *order; + const char *order; /** The x co-ordinate of the base point on the curve (hex) */ - char *Gx; + const char *Gx; /** The y co-ordinate of the base point on the curve (hex) */ - char *Gy; + const char *Gy; /** The co-factor */ unsigned long cofactor; - /** The OID stucture */ - oid_st oid; + /** The OID */ + unsigned long oid[16]; + unsigned long oidlen; } ltc_ecc_set_type; /** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */ @@ -299,18 +297,36 @@ typedef struct { void *z; } ecc_point; +/** ECC key's domain parameters */ +typedef struct { + /** The size of the curve in octets */ + int size; + /** The prime that defines the field the curve is in */ + void *prime; + /** The fields A param */ + void *A; + /** The fields B param */ + void *B; + /** The order of the curve */ + void *order; + /** The base point G on the curve */ + ecc_point base; + /** The co-factor */ + unsigned long cofactor; + /** The OID */ + unsigned long oid[16]; + unsigned long oidlen; +} ltc_ecc_dp; + /** An ECC key */ typedef struct { /** Type of key, PK_PRIVATE or PK_PUBLIC */ int type; - /** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */ - int idx; + /** Structure with domain parameters */ + ltc_ecc_dp dp; - /** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */ - const ltc_ecc_set_type *dp; - - /** The public key */ + /** Structure with the public key */ ecc_point pubkey; /** The private key */ @@ -324,12 +340,11 @@ int ecc_test(void); void ecc_sizes(int *low, int *high); int ecc_get_size(ecc_key *key); -int ecc_dp_init(ltc_ecc_set_type *dp); -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); -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); -int ecc_dp_set_by_oid(ltc_ecc_set_type *dp, unsigned long *oid, unsigned long oidsize); -int ecc_dp_fill_from_sets(ltc_ecc_set_type *dp); -int ecc_dp_clear(ltc_ecc_set_type *dp); +int ecc_get_set_by_name(const char* name, const ltc_ecc_set_type** dp); +int ecc_set_dp(const ltc_ecc_set_type *set, ecc_key *key); +int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key); +int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key); +int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key); int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp); @@ -338,15 +353,15 @@ void ecc_free(ecc_key *key); int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp); -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); -int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); -int ecc_import_full(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp); -int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); -int ecc_import_raw(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp); int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen); int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key); -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 ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); +int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ecc_key *key); +int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key); int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, unsigned char *out, unsigned long *outlen); @@ -376,24 +391,31 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, ecc_key *key); -int ecc_verify_key(ecc_key *key); + +#ifdef LTC_SOURCE +/* INTERNAL ONLY - it should be later moved to src/headers/tomcrypt_internal.h */ + +int ecc_set_dp_bn(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key); +int ecc_set_dp_oid(unsigned long *oid, unsigned long oidsize, ecc_key *key); +int ecc_set_dp_copy(ecc_key *srckey, ecc_key *key); +int ecc_set_dp_size(int size, ecc_key *key); /* low level functions */ ecc_point *ltc_ecc_new_point(void); void ltc_ecc_del_point(ecc_point *p); -int ltc_ecc_is_valid_idx(int n); -int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y); -int ltc_ecc_is_point_at_infinity(ecc_point *p, void *modulus); +int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y); +int ltc_ecc_is_point_at_infinity(const ecc_point *p, void *modulus); int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y); int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed); +int ltc_ecc_verify_key(ecc_key *key); /* point ops (mp == montgomery digit) */ #if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC) /* R = 2P */ -int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *a, void *modulus, void *mp); +int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp); /* R = P + Q */ -int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *a, 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); #endif #if defined(LTC_MECC_FP) @@ -411,23 +433,23 @@ void ltc_ecc_fp_tablelock(int lock); #endif /* R = kG */ -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); #ifdef LTC_ECC_SHAMIR /* kA*A + kB*B = C */ -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); #ifdef LTC_MECC_FP /* Shamir's trick with optimized point multiplication using fixed point cache */ -int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, - ecc_point *B, void *kB, - ecc_point *C, - void *a, - void *modulus); +int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus); #endif #endif @@ -436,6 +458,8 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, /* map P to affine from projective */ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp); +#endif /* LTC_SOURCE */ + #endif #ifdef LTC_MDSA @@ -549,12 +573,22 @@ typedef enum ltc_asn1_type_ { LTC_ASN1_SETOF, LTC_ASN1_RAW_BIT_STRING, LTC_ASN1_TELETEX_STRING, - LTC_ASN1_CONSTRUCTED, - LTC_ASN1_CONTEXT_SPECIFIC, - /* 20 */ LTC_ASN1_GENERALIZEDTIME, + LTC_ASN1_CUSTOM_TYPE, } ltc_asn1_type; +typedef enum { + LTC_ASN1_CL_UNIVERSAL = 0x0, + LTC_ASN1_CL_APPLICATION = 0x1, + LTC_ASN1_CL_CONTEXT_SPECIFIC = 0x2, + LTC_ASN1_CL_PRIVATE = 0x3, +} ltc_asn1_class; + +typedef enum { + LTC_ASN1_PC_PRIMITIVE = 0x0, + LTC_ASN1_PC_CONSTRUCTED = 0x1, +} ltc_asn1_pc; + /** A LTC ASN.1 list type */ typedef struct ltc_asn1_list_ { /** The LTC ASN.1 enumerated type identifier */ @@ -563,12 +597,17 @@ typedef struct ltc_asn1_list_ { void *data; /** The size of the input or resulting output */ unsigned long size; - /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */ + /** The used flag + * 1. This is used by the CHOICE ASN.1 type to indicate which choice was made + * 2. This is used by the ASN.1 decoder to indicate if an element is used + * 3. This is used by the flexi-decoder to indicate the first byte of the identifier */ int used; /** Flag used to indicate optional items in ASN.1 sequences */ int optional; - /** Flag used to indicate context specific tags on ASN.1 sequence items */ - unsigned char tag; + /** ASN.1 identifier */ + ltc_asn1_class class; + ltc_asn1_pc pc; + ulong64 tag; /** prev/next entry in the list */ struct ltc_asn1_list_ *prev, *next, *child, *parent; } ltc_asn1_list; @@ -581,46 +620,120 @@ typedef struct ltc_asn1_list_ { LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \ LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \ LTC_MACRO_list[LTC_MACRO_temp].used = 0; \ - LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \ LTC_MACRO_list[LTC_MACRO_temp].optional = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].class = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].pc = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \ + } while (0) + +#define __LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \ + do { \ + int LTC_MACRO_temp = (index); \ + ltc_asn1_list *LTC_MACRO_list = (list); \ + LTC_MACRO_list[LTC_MACRO_temp].type = LTC_ASN1_CUSTOM_TYPE; \ + LTC_MACRO_list[LTC_MACRO_temp].class = (Class); \ + LTC_MACRO_list[LTC_MACRO_temp].pc = (Pc); \ + LTC_MACRO_list[LTC_MACRO_temp].tag = (Tag); \ + } while (0) + +#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \ + do { \ + int LTC_MACRO_temp##__LINE__ = (index); \ + LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, 1); \ + __LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \ + } while (0) + +#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \ + do { \ + int LTC_MACRO_temp##__LINE__ = (index); \ + LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, Size); \ + __LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_PRIMITIVE, Tag); \ + list[LTC_MACRO_temp##__LINE__].used = (int)(Type); \ } while (0) +extern const char* der_asn1_class_to_string_map[]; +extern const unsigned long der_asn1_class_to_string_map_sz; + +extern const char* der_asn1_pc_to_string_map[]; +extern const unsigned long der_asn1_pc_to_string_map_sz; + +extern const char* der_asn1_tag_to_string_map[]; +extern const unsigned long der_asn1_tag_to_string_map_sz; + /* SEQUENCE */ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen, int type_of); #define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE) +/** The supported bitmap for all the + * decoders with a `flags` argument. + */ +enum ltc_der_seq { + LTC_DER_SEQ_ZERO = 0x0u, + + /** Bit0 - [0]=Unordered (SET or SETOF) + * [1]=Ordered (SEQUENCE) */ + LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO, + LTC_DER_SEQ_ORDERED = 0x1u, + + /** Bit1 - [0]=Relaxed + * [1]=Strict */ + LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO, + LTC_DER_SEQ_STRICT = 0x2u, + + /** Alternative naming */ + LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED, + LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED, +}; + int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, - ltc_asn1_list *list, unsigned long outlen, int ordered); + ltc_asn1_list *list, unsigned long outlen, unsigned int flags); -#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1) +#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED) +#define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT) int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, unsigned long *outlen); +/* Custom-types */ +int der_encode_custom_type(const ltc_asn1_list *root, + unsigned char *out, unsigned long *outlen); + +int der_decode_custom_type(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root); + +int der_length_custom_type(const ltc_asn1_list *root, + unsigned long *outlen, + unsigned long *payloadlen); + #ifdef LTC_SOURCE /* internal helper functions */ +int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root, + ltc_asn1_list *list, unsigned long outlen, unsigned int flags); + +int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen); +int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id); +int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen); + +int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen); +int der_decode_asn1_length(const unsigned char* len, unsigned long* lenlen, unsigned long* outlen); +int der_length_asn1_length(unsigned long len, unsigned long *outlen); + int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen, unsigned long *outlen, unsigned long *payloadlen); -/* SUBJECT PUBLIC KEY INFO */ -int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, - unsigned int algorithm, void* public_key, unsigned long public_key_len, - unsigned long parameters_type, void* parameters, unsigned long parameters_len); -int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, - unsigned int algorithm, void* public_key, unsigned long* public_key_len, - unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len); +extern const ltc_asn1_type der_asn1_tag_to_type_map[]; +extern const unsigned long der_asn1_tag_to_type_map_sz; -int der_decode_subject_public_key_info_ex(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); +extern const int der_asn1_type_to_identifier_map[]; +extern const unsigned long der_asn1_type_to_identifier_map_sz; #endif /* LTC_SOURCE */ /* SET */ -#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0) +#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET) #define der_length_set der_length_sequence int der_encode_set(ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen); @@ -631,6 +744,10 @@ int der_encode_setof(ltc_asn1_list *list, unsigned long inlen, /* VA list handy helpers with triplets of <type, size, data> */ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...); +#ifdef LTC_SOURCE +/* internal helper functions */ +int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...); +#endif /* LTC_SOURCE */ /* FLEXI DECODER handle unknown list decoder */ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); @@ -786,6 +903,17 @@ int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, int der_length_generalizedtime(ltc_generalizedtime *gtime, unsigned long *outlen); +#ifdef LTC_SOURCE +/* internal helper functions */ +/* SUBJECT PUBLIC KEY INFO */ +int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, + unsigned int algorithm, void* public_key, unsigned long public_key_len, + unsigned long parameters_type, void* parameters, unsigned long parameters_len); + +int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, + unsigned int algorithm, void* public_key, unsigned long* public_key_len, + unsigned long parameters_type, void* parameters, unsigned long *parameters_len); +#endif /* LTC_SOURCE */ #endif diff --git a/src/ltc/mac/blake2/blake2bmac_file.c b/src/ltc/mac/blake2/blake2bmac_file.c index 64c9e4d1..c1e9c6b5 100644 --- a/src/ltc/mac/blake2/blake2bmac_file.c +++ b/src/ltc/mac/blake2/blake2bmac_file.c @@ -23,6 +23,11 @@ int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) { #ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); return CRYPT_NOP; #else blake2bmac_state st; diff --git a/src/ltc/mac/blake2/blake2smac_file.c b/src/ltc/mac/blake2/blake2smac_file.c index c5248a29..1ac66797 100644 --- a/src/ltc/mac/blake2/blake2smac_file.c +++ b/src/ltc/mac/blake2/blake2smac_file.c @@ -23,6 +23,11 @@ int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) { #ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); return CRYPT_NOP; #else blake2smac_state st; diff --git a/src/ltc/mac/f9/f9_file.c b/src/ltc/mac/f9/f9_file.c index a6e6532c..04d509bf 100644 --- a/src/ltc/mac/f9/f9_file.c +++ b/src/ltc/mac/f9/f9_file.c @@ -31,6 +31,12 @@ int f9_file(int cipher, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; diff --git a/src/ltc/mac/hmac/hmac_file.c b/src/ltc/mac/hmac/hmac_file.c index 2d10e21c..0e1a1631 100644 --- a/src/ltc/mac/hmac/hmac_file.c +++ b/src/ltc/mac/hmac/hmac_file.c @@ -30,6 +30,12 @@ int hmac_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(hash); + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else hmac_state hmac; diff --git a/src/ltc/mac/omac/omac_file.c b/src/ltc/mac/omac/omac_file.c index a9104e8e..3f6a85d0 100644 --- a/src/ltc/mac/omac/omac_file.c +++ b/src/ltc/mac/omac/omac_file.c @@ -31,6 +31,12 @@ int omac_file(int cipher, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; diff --git a/src/ltc/mac/pmac/pmac_file.c b/src/ltc/mac/pmac/pmac_file.c index abe04f1e..fe202a2f 100644 --- a/src/ltc/mac/pmac/pmac_file.c +++ b/src/ltc/mac/pmac/pmac_file.c @@ -31,6 +31,12 @@ int pmac_file(int cipher, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; diff --git a/src/ltc/mac/poly1305/poly1305_file.c b/src/ltc/mac/poly1305/poly1305_file.c index 77263056..e57437b3 100644 --- a/src/ltc/mac/poly1305/poly1305_file.c +++ b/src/ltc/mac/poly1305/poly1305_file.c @@ -28,6 +28,11 @@ int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) { #ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); return CRYPT_NOP; #else poly1305_state st; diff --git a/src/ltc/mac/xcbc/xcbc_file.c b/src/ltc/mac/xcbc/xcbc_file.c index f121cd0e..27eb0dec 100644 --- a/src/ltc/mac/xcbc/xcbc_file.c +++ b/src/ltc/mac/xcbc/xcbc_file.c @@ -31,6 +31,12 @@ int xcbc_file(int cipher, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; diff --git a/src/ltc/math/rand_bn.c b/src/ltc/math/rand_bn.c index a42ba642..aa6539cc 100644 --- a/src/ltc/math/rand_bn.c +++ b/src/ltc/math/rand_bn.c @@ -8,7 +8,7 @@ */ #include "tomcrypt.h" -#ifdef LTC_MDSA +#if defined(LTC_MDSA) || defined(LTC_MECC) /** Generate a random number N with given bitlength (note: MSB can be 0) */ diff --git a/src/ltc/math/tfm_desc.c b/src/ltc/math/tfm_desc.c index 2a5a57d9..9247db65 100644 --- a/src/ltc/math/tfm_desc.c +++ b/src/ltc/math/tfm_desc.c @@ -265,6 +265,16 @@ static int sqr(void *a, void *b) return CRYPT_OK; } +/* sqrtmod_prime */ +static int sqrtmod_prime(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + fprintf(stderr, "TFM does not support sqrtmod_prime\n"); /* XXX-FIXME */ + return CRYPT_ERROR; +} + /* div */ static int divide(void *a, void *b, void *c, void *d) { @@ -424,7 +434,7 @@ static int isprime(void *a, int b, int *c) #if defined(LTC_MECC) && defined(LTC_MECC_ACCEL) -static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *Mp) +static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *Mp) { fp_int t1, t2; fp_digit mp; @@ -445,6 +455,14 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu fp_copy(P->z, R->z); } + if (ltc_ecc_is_point_at_infinity(P, modulus)) { + /* if P is point at infinity >> Result = point at infinity */ + ltc_mp.set_int(R->x, 1); + ltc_mp.set_int(R->y, 1); + ltc_mp.set_int(R->z, 0); + return CRYPT_OK; + } + /* t1 = Z * Z */ fp_sqr(R->z, &t1); fp_montgomery_reduce(&t1, modulus, mp); @@ -457,28 +475,56 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu fp_sub(R->z, modulus, R->z); } - /* &t2 = X - T1 */ - fp_sub(R->x, &t1, &t2); - if (fp_cmp_d(&t2, 0) == FP_LT) { - fp_add(&t2, modulus, &t2); - } - /* T1 = X + T1 */ - fp_add(&t1, R->x, &t1); - if (fp_cmp(&t1, modulus) != FP_LT) { - fp_sub(&t1, modulus, &t1); - } - /* T2 = T1 * T2 */ - fp_mul(&t1, &t2, &t2); - fp_montgomery_reduce(&t2, modulus, mp); - /* T1 = 2T2 */ - fp_add(&t2, &t2, &t1); - if (fp_cmp(&t1, modulus) != FP_LT) { - fp_sub(&t1, modulus, &t1); - } - /* T1 = T1 + T2 */ - fp_add(&t1, &t2, &t1); - if (fp_cmp(&t1, modulus) != FP_LT) { - fp_sub(&t1, modulus, &t1); + if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ + /* T2 = X - T1 */ + fp_sub(R->x, &t1, &t2); + if (fp_cmp_d(&t2, 0) == LTC_MP_LT) { + fp_add(&t2, modulus, &t2); + } + /* T1 = X + T1 */ + fp_add(&t1, R->x, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T2 = T1 * T2 */ + fp_mul(&t1, &t2, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = 2T2 */ + fp_add(&t2, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + } + else { + /* T2 = T1 * T1 */ + fp_sqr(&t1, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T2 * a */ + fp_mul(&t2, ma, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* T2 = X * X */ + fp_sqr(R->x, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } } /* Y = 2Y */ @@ -541,7 +587,7 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu @param Mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ -static int tfm_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *Mp) +static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *Mp) { fp_int t1, t2, x, y, z; fp_digit mp; @@ -560,12 +606,28 @@ static int tfm_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R fp_init(&y); fp_init(&z); + if (ltc_ecc_is_point_at_infinity(P, modulus)) { + /* P is point at infinity >> Result = Q */ + ltc_mp.copy(Q->x, R->x); + ltc_mp.copy(Q->y, R->y); + ltc_mp.copy(Q->z, R->z); + return CRYPT_OK; + } + + if (ltc_ecc_is_point_at_infinity(Q, modulus)) { + /* Q is point at infinity >> Result = P */ + ltc_mp.copy(P->x, R->x); + ltc_mp.copy(P->y, R->y); + ltc_mp.copy(P->z, R->z); + return CRYPT_OK; + } + /* should we dbl instead? */ fp_sub(modulus, Q->y, &t1); if ( (fp_cmp(P->x, Q->x) == FP_EQ) && (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) && (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) { - return tfm_ecc_projective_dbl_point(P, R, modulus, Mp); + return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp); } fp_copy(P->x, &x); @@ -741,6 +803,7 @@ const ltc_math_descriptor tfm_desc = { &mul, &muli, &sqr, + &sqrtmod_prime, ÷, &div_2, &modi, diff --git a/src/ltc/misc/crypt/crypt_constants.c b/src/ltc/misc/crypt/crypt_constants.c index a7418d5e..9e76322c 100644 --- a/src/ltc/misc/crypt/crypt_constants.c +++ b/src/ltc/misc/crypt/crypt_constants.c @@ -47,7 +47,7 @@ static const crypt_constant _crypt_constants[] = { _C_STRINGIFY(CRYPT_FILE_NOTFOUND), _C_STRINGIFY(CRYPT_PK_INVALID_TYPE), _C_STRINGIFY(CRYPT_OVERFLOW), - _C_STRINGIFY(CRYPT_UNUSED1), + _C_STRINGIFY(CRYPT_PK_ASN1_ERROR), _C_STRINGIFY(CRYPT_INPUT_TOO_LONG), _C_STRINGIFY(CRYPT_PK_INVALID_SIZE), _C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE), @@ -129,9 +129,8 @@ static const crypt_constant _crypt_constants[] = { _C_STRINGIFY(LTC_ASN1_SETOF), _C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING), _C_STRINGIFY(LTC_ASN1_TELETEX_STRING), - _C_STRINGIFY(LTC_ASN1_CONSTRUCTED), - _C_STRINGIFY(LTC_ASN1_CONTEXT_SPECIFIC), _C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME), + _C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE), #endif #ifdef LTC_CTR_MODE diff --git a/src/ltc/misc/error_to_string.c b/src/ltc/misc/error_to_string.c index 707f8359..3d168286 100644 --- a/src/ltc/misc/error_to_string.c +++ b/src/ltc/misc/error_to_string.c @@ -46,7 +46,7 @@ static const char * const err_2_str[] = "An overflow of a value was detected/prevented.", - "UNUSED1.", + "An ASN.1 decoding error occurred.", "The input was longer than expected.", diff --git a/src/ltc/misc/pk_get_oid.c b/src/ltc/misc/pk_get_oid.c index 8ea3e075..003925aa 100644 --- a/src/ltc/misc/pk_get_oid.c +++ b/src/ltc/misc/pk_get_oid.c @@ -45,7 +45,7 @@ int pk_get_oid(int pk, oid_st *st) case PKA_EC: XMEMCPY(st, &ec_oid, sizeof(*st)); break; - case EC_PRIME_FIELD: + case PKA_EC_PRIMEF: XMEMCPY(st, &ec_primef, sizeof(*st)); break; default: diff --git a/src/ltc/modes/ctr/ctr_encrypt.c b/src/ltc/modes/ctr/ctr_encrypt.c index ecc7b01b..7319cf53 100644 --- a/src/ltc/modes/ctr/ctr_encrypt.c +++ b/src/ltc/modes/ctr/ctr_encrypt.c @@ -53,6 +53,8 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) { return err; } + pt += (len / ctr->blocklen) * ctr->blocklen; + ct += (len / ctr->blocklen) * ctr->blocklen; len %= ctr->blocklen; } 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..95fdd846 --- /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 (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 = <c_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 = <c_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 = <c_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, <c_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(<c_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; } |