Skip to content

Commit 3ff87df

Browse files
committed
ECC: fix KDSA sign behavior
If we are in fips mode, the k-value is created via openssl. This may cause a cc=2 (random number not invertible) from the KDSA instruction. In this case loop over KDSA with new random values. But don't loop over calls to KDSA with unchanged k-value in the non-fips case. This could lead to an endless loop. Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
1 parent 9d1be31 commit 3ff87df

1 file changed

Lines changed: 54 additions & 21 deletions

File tree

src/s390_ecc.c

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ extern OSSL_LIB_CTX *openssl_libctx;
4242

4343
#define CPRBXSIZE (sizeof(struct CPRBX))
4444
#define PARMBSIZE (2048)
45+
#define MAX_KDSA_RETRIES 10000
4546

4647

4748
static int eckeygen_cpacf(ICA_EC_KEY *key);
@@ -1715,7 +1716,7 @@ struct { \
17151716
#undef DEF_PARAM
17161717

17171718
unsigned long fc;
1718-
size_t off;
1719+
size_t off, counter = 0;
17191720
int rc;
17201721

17211722
memset(&param, 0, sizeof(param));
@@ -1743,16 +1744,25 @@ struct { \
17431744
#ifdef ICA_FIPS
17441745
if (fips & ICA_FIPS_MODE) {
17451746
fc |= 0x80; /* deterministic signature */
1746-
RAND_bytes(param.P256.rand + off, sizeof(param.P256.rand) - off);
1747+
do {
1748+
/* If the random number is not invertible, s390_kdsa will
1749+
* cause to loop. Same for p384 and p521 below. */
1750+
if (RAND_bytes(param.P256.rand + off, sizeof(param.P256.rand) - off) != 1) {
1751+
rc = EIO;
1752+
break;
1753+
}
1754+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
1755+
} while ((rc != 0) && (++counter < MAX_KDSA_RETRIES));
1756+
} else {
1757+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
17471758
}
1759+
#else
1760+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
17481761
#endif
1749-
rc = s390_kdsa(fc, param.buff, NULL, 0);
17501762
} else {
17511763
fc |= 0x80; /* deterministic signature */
1752-
do {
1753-
memcpy(param.P256.rand + off, k, sizeof(param.P256.rand) - off);
1754-
rc = s390_kdsa(fc, param.buff, NULL, 0);
1755-
} while (rc);
1764+
memcpy(param.P256.rand + off, k, sizeof(param.P256.rand) - off);
1765+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
17561766
}
17571767

17581768
memcpy(sig, param.P256.sig_r + off,
@@ -1787,16 +1797,23 @@ struct { \
17871797
#ifdef ICA_FIPS
17881798
if (fips & ICA_FIPS_MODE) {
17891799
fc |= 0x80; /* deterministic signature */
1790-
RAND_bytes(param.P384.rand + off, sizeof(param.P384.rand) - off);
1800+
do {
1801+
if (RAND_bytes(param.P384.rand + off, sizeof(param.P384.rand) - off) != 1) {
1802+
rc = EIO;
1803+
break;
1804+
}
1805+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
1806+
} while ((rc != 0) && (++counter < MAX_KDSA_RETRIES));
1807+
} else {
1808+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
17911809
}
1810+
#else
1811+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
17921812
#endif
1793-
rc = s390_kdsa(fc, param.buff, NULL, 0);
17941813
} else {
17951814
fc |= 0x80; /* deterministic signature */
1796-
do {
1797-
memcpy(param.P384.rand + off, k, sizeof(param.P384.rand) - off);
1798-
rc = s390_kdsa(fc, param.buff, NULL, 0);
1799-
} while (rc);
1815+
memcpy(param.P384.rand + off, k, sizeof(param.P384.rand) - off);
1816+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
18001817
}
18011818

18021819
memcpy(sig, param.P384.sig_r + off,
@@ -1830,19 +1847,35 @@ struct { \
18301847
if (k == NULL) {
18311848
#ifdef ICA_FIPS
18321849
if (fips & ICA_FIPS_MODE) {
1833-
/* Random number must be invertible by the order of the curve.
1834-
* Use one byte less */
18351850
fc |= 0x80; /* deterministic signature */
1836-
RAND_bytes(param.P521.rand + off + 1, sizeof(param.P521.rand) - off - 1);
1851+
do {
1852+
if (RAND_bytes(param.P521.rand + off, sizeof(param.P521.rand) - off) != 1) {
1853+
rc = EIO;
1854+
break;
1855+
}
1856+
/*
1857+
* Before calling KDSA, set the first 7 bits of the leftmost
1858+
* byte of the generated random number to zero, which
1859+
* actually makes the random number a 521-bit value. If the
1860+
* random nonce has anything else than 0x01 or 0x00 in the
1861+
* very first byte, it will be larger than the order, and
1862+
* thus KDSA will fail with CC=2 and the loop takes a retry.
1863+
* So this just minimizes the number of retries without
1864+
* decreasing security.
1865+
*/
1866+
*(param.P521.rand + off) &= 0x01;
1867+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
1868+
} while ((rc != 0) && (++counter < MAX_KDSA_RETRIES));
1869+
} else {
1870+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
18371871
}
1872+
#else
1873+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
18381874
#endif
1839-
rc = s390_kdsa(fc, param.buff, NULL, 0);
18401875
} else {
18411876
fc |= 0x80; /* deterministic signature */
1842-
do {
1843-
memcpy(param.P521.rand + off, k, sizeof(param.P521.rand) - off);
1844-
rc = s390_kdsa(fc, param.buff, NULL, 0);
1845-
} while (rc);
1877+
memcpy(param.P521.rand + off, k, sizeof(param.P521.rand) - off);
1878+
rc = s390_kdsa(fc, param.buff, NULL, 0) ? EIO : 0;
18461879
}
18471880

18481881
memcpy(sig, param.P521.sig_r + off,

0 commit comments

Comments
 (0)