Skip to content

Commit d062d0e

Browse files
authored
Merge pull request #446 from libtom/pr/wycheproof-fail-changed-seq-tag
Wycheproof failing ECC tests
2 parents 7d0d079 + 66a2e73 commit d062d0e

13 files changed

Lines changed: 300 additions & 8 deletions

‎src/headers/tomcrypt_pk.h‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,9 +960,17 @@ enum ltc_der_seq {
960960
LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO,
961961
LTC_DER_SEQ_STRICT = 0x2u,
962962

963+
/** Bit2 - [0]=Relaxed Length Check
964+
* [1]=Strict Length Check */
965+
LTC_DER_SEQ_LEN_RELAXED = LTC_DER_SEQ_ZERO,
966+
LTC_DER_SEQ_LEN_STRICT = 0x4u,
967+
963968
/** Alternative naming */
964969
LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED,
965970
LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED,
971+
972+
LTC_DER_SEQ_ALL_STRICT = LTC_DER_SEQ_STRICT | LTC_DER_SEQ_LEN_STRICT,
973+
966974
};
967975

968976
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,

‎src/headers/tomcrypt_private.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,8 @@ int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, lt
756756
int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen);
757757

758758
int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen);
759-
int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen);
759+
int der_decode_asn1_length_ex(const unsigned char *in, unsigned long *inlen, unsigned long *outlen, unsigned int flags);
760+
#define der_decode_asn1_length(i, il, ol) der_decode_asn1_length_ex(i, il, ol, 0)
760761
int der_length_asn1_length(unsigned long len, unsigned long *outlen);
761762

762763
int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,

‎src/math/fp/ltc_ecc_fp_mulmod.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,11 @@ int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulu
12241224
int idx, err;
12251225
void *mp, *mu;
12261226

1227+
if (ltc_mp_iszero(k) == LTC_MP_YES) {
1228+
/* 0 * G is the point at infinity */
1229+
return ltc_ecc_set_point_xyz(1, 1, 0, R);
1230+
}
1231+
12271232
mp = NULL;
12281233
mu = NULL;
12291234
LTC_MUTEX_LOCK(&ltc_ecc_fp_lock);

‎src/math/tfm_desc.c‎

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,14 @@ static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, const
469469
return CRYPT_OK;
470470
}
471471

472+
/* Y == 0 or Z == 0 doubles to infinity. */
473+
if (fp_cmp_d(R->y, 0) == FP_EQ || fp_cmp_d(R->z, 0) == FP_EQ) {
474+
ltc_mp.set_int(R->x, 1);
475+
ltc_mp.set_int(R->y, 1);
476+
ltc_mp.set_int(R->z, 0);
477+
return CRYPT_OK;
478+
}
479+
472480
/* t1 = Z * Z */
473481
fp_sqr(R->z, &t1);
474482
fp_montgomery_reduce(&t1, TFM_UNCONST(void *)modulus, mp);
@@ -597,7 +605,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
597605
{
598606
fp_int t1, t2, x, y, z;
599607
fp_digit mp;
600-
int err, inf;
608+
int err, inf, x_or_y_is_zero;
601609

602610
LTC_ARGCHK(P != NULL);
603611
LTC_ARGCHK(Q != NULL);
@@ -613,6 +621,29 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
613621
fp_init(&y);
614622
fp_init(&z);
615623

624+
/* treat internal Z == 0 states as infinity */
625+
if (P->z != NULL && fp_cmp_d(P->z, 0) == FP_EQ) {
626+
if (Q->z != NULL && fp_cmp_d(Q->z, 0) == FP_EQ) {
627+
/* inf + inf = inf */
628+
ltc_mp.set_int(R->x, 1);
629+
ltc_mp.set_int(R->y, 1);
630+
ltc_mp.set_int(R->z, 0);
631+
} else {
632+
/* inf + Q = Q */
633+
ltc_mp.copy(Q->x, R->x);
634+
ltc_mp.copy(Q->y, R->y);
635+
ltc_mp.copy(Q->z, R->z);
636+
}
637+
return CRYPT_OK;
638+
}
639+
if (Q->z != NULL && fp_cmp_d(Q->z, 0) == FP_EQ) {
640+
/* P + inf = P */
641+
ltc_mp.copy(P->x, R->x);
642+
ltc_mp.copy(P->y, R->y);
643+
ltc_mp.copy(P->z, R->z);
644+
return CRYPT_OK;
645+
}
646+
616647
if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
617648
if (inf) {
618649
/* P is point at infinity >> Result = Q */
@@ -636,6 +667,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
636667
if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
637668
(Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
638669
(fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
670+
dbl_point:
639671
return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp);
640672
}
641673

@@ -735,6 +767,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
735767
if (fp_cmp_d(&x, 0) == FP_LT) {
736768
fp_add(&x, TFM_UNCONST(void *)modulus, &x);
737769
}
770+
x_or_y_is_zero = fp_cmp_d(&x, 0) == FP_EQ;
738771

739772
/* T2 = T2 - X */
740773
fp_sub(&t2, &x, &t2);
@@ -759,6 +792,11 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
759792
fp_add(&y, TFM_UNCONST(void *)modulus, &y);
760793
}
761794
fp_div_2(&y, &y);
795+
x_or_y_is_zero |= fp_cmp_d(&y, 0) == LTC_MP_EQ;
796+
797+
if (x_or_y_is_zero) {
798+
goto dbl_point;
799+
}
762800

763801
fp_copy(&x, R->x);
764802
fp_copy(&y, R->y);

‎src/pk/asn1/der/custom_type/der_decode_custom_type.c‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
4747
int err, seq_err, i, ordered;
4848
ltc_asn1_type type;
4949
ltc_asn1_list ident;
50+
unsigned int f;
5051
unsigned long size, x, y, z, blksize;
5152
unsigned char* in_new = NULL;
5253
void *data;
@@ -63,7 +64,8 @@ int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
6364
LTC_ARGCHK(list != NULL);
6465

6566
/* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
66-
if (in[x] != 0x30 && in[x] != 0x31) {
67+
f = flags & ~(LTC_DER_SEQ_ALL_STRICT);
68+
if (((f == LTC_DER_SEQ_SEQUENCE) && (in[x] != 0x30)) || (((f == LTC_DER_SEQ_SET) && (in[x] != 0x31)))) {
6769
return CRYPT_INVALID_PACKET;
6870
}
6971
++x;
@@ -116,7 +118,7 @@ int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
116118
} else {
117119

118120
y = inlen - x;
119-
if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) {
121+
if ((err = der_decode_asn1_length_ex(&in[x], &y, &blksize, flags)) != CRYPT_OK) {
120122
goto LBL_ERR;
121123
}
122124
x += y;

‎src/pk/asn1/der/general/der_decode_asn1_length.c‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
@param outlen [out] The decoded ASN.1 length
1616
@return CRYPT_OK if successful
1717
*/
18-
int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen)
18+
int der_decode_asn1_length_ex(const unsigned char *in, unsigned long *inlen, unsigned long *outlen, unsigned int flags)
1919
{
2020
unsigned long real_len, decoded_len, offset, i;
2121

@@ -42,10 +42,17 @@ int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsign
4242
if (real_len > (*inlen - 1)) {
4343
return CRYPT_BUFFER_OVERFLOW;
4444
}
45+
flags &= LTC_DER_SEQ_LEN_STRICT;
4546
decoded_len = 0;
4647
offset = 1 + real_len;
4748
for (i = 0; i < real_len; i++) {
4849
decoded_len = (decoded_len << 8) | in[1 + i];
50+
if ((flags == LTC_DER_SEQ_LEN_STRICT) && (decoded_len == 0)) {
51+
return CRYPT_PK_ASN1_ERROR;
52+
}
53+
}
54+
if ((flags == LTC_DER_SEQ_LEN_STRICT) && (real_len == 1) && (decoded_len < 128)) {
55+
return CRYPT_PK_ASN1_ERROR;
4956
}
5057
}
5158

‎src/pk/ecc/ecc_verify_hash.c‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ int ecc_verify_hash_v2(const unsigned char *sig,
4646
int *stat,
4747
const ecc_key *key)
4848
{
49+
LTC_ARGCHK(stat != NULL);
50+
*stat = 0;
4951
if (opts->type < 0 || opts->type >= LTC_ARRAY_SIZE(s_ecc_verify_hash))
5052
return CRYPT_PK_INVALID_TYPE;
5153
if (s_ecc_verify_hash[opts->type] == NULL)

‎src/pk/ecc/ecc_verify_hash_x962.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ int ecc_verify_hash_x962(const unsigned char *sig, unsigned long siglen,
2222
if ((err = ltc_mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err;
2323

2424
/* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */
25-
if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
25+
if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_ALL_STRICT,
2626
LTC_ASN1_INTEGER, 1UL, r,
2727
LTC_ASN1_INTEGER, 1UL, s,
2828
LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; }

‎src/pk/ecc/ltc_ecc_mulmod.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ int ltc_ecc_mulmod(const void *k, const ecc_point *G, ecc_point *R, const void *
4242
/* return the point at infinity */
4343
return ltc_ecc_set_point_xyz(1, 1, 0, R);
4444
}
45+
if (ltc_mp_iszero(k) == LTC_MP_YES) {
46+
/* 0 * G is the point at infinity */
47+
return ltc_ecc_set_point_xyz(1, 1, 0, R);
48+
}
4549

4650
/* init montgomery reduction */
4751
if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }

‎src/pk/ecc/ltc_ecc_mulmod_timing.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ int ltc_ecc_mulmod(const void *k, const ecc_point *G, ecc_point *R, const void *
4040
/* return the point at infinity */
4141
return ltc_ecc_set_point_xyz(1, 1, 0, R);
4242
}
43+
if (ltc_mp_iszero(k) == LTC_MP_YES) {
44+
/* 0 * G is the point at infinity */
45+
return ltc_ecc_set_point_xyz(1, 1, 0, R);
46+
}
4347

4448
/* init montgomery reduction */
4549
if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }

0 commit comments

Comments
 (0)