When setting expiration dates: Prevent integer overflow

This commit is contained in:
Paul Schaub 2022-06-01 13:36:00 +02:00
parent 70a861611c
commit 44c32d0620
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
2 changed files with 40 additions and 7 deletions

View File

@ -212,9 +212,7 @@ public class SignatureSubpackets
@Override
public SignatureSubpackets setSignatureExpirationTime(boolean isCritical, long seconds) {
if (seconds < 0) {
throw new IllegalArgumentException("Expiration time cannot be negative.");
}
enforceBounds(seconds);
return setSignatureExpirationTime(new SignatureExpirationTime(isCritical, seconds));
}
@ -285,12 +283,19 @@ public class SignatureSubpackets
@Override
public SignatureSubpackets setKeyExpirationTime(boolean isCritical, long secondsFromCreationToExpiration) {
if (secondsFromCreationToExpiration < 0) {
throw new IllegalArgumentException("Seconds from key creation to expiration cannot be less than 0.");
}
enforceBounds(secondsFromCreationToExpiration);
return setKeyExpirationTime(new KeyExpirationTime(isCritical, secondsFromCreationToExpiration));
}
private void enforceBounds(long secondsFromCreationToExpiration) {
if (secondsFromCreationToExpiration < 0) {
throw new IllegalArgumentException("Seconds from creation to expiration cannot be less than 0.");
}
if (secondsFromCreationToExpiration > 0xffffffffL) {
throw new IllegalArgumentException("Integer overflow. Seconds from creation to expiration cannot be larger than 0xffffffff");
}
}
@Override
public SignatureSubpackets setKeyExpirationTime(@Nullable KeyExpirationTime keyExpirationTime) {
this.keyExpirationTime = keyExpirationTime;

View File

@ -7,6 +7,7 @@ package org.pgpainless.key.modification;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
import java.util.Calendar;
@ -14,13 +15,14 @@ import java.util.Date;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.junit.JUtils;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.JUtils;
import org.pgpainless.PGPainless;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.TestKeys;
import org.pgpainless.key.info.KeyRingInfo;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
import org.pgpainless.util.DateUtil;
import org.pgpainless.util.TestAllImplementations;
@ -93,4 +95,30 @@ public class ChangeExpirationTest {
sInfo = PGPainless.inspectKeyRing(secretKeys);
assertNull(sInfo.getPrimaryKeyExpirationDate());
}
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testExtremeExpirationDates() throws PGPException, IOException {
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
// seconds from 2021 to 2199 will overflow 32bit integers
Date farAwayExpiration = DateUtil.parseUTCDate("2199-01-01 00:00:00 UTC");
final PGPSecretKeyRing finalKeys = secretKeys;
assertThrows(IllegalArgumentException.class, () ->
PGPainless.modifyKeyRing(finalKeys)
.setExpirationDate(farAwayExpiration, protector)
.done());
Date notSoFarAwayExpiration = DateUtil.parseUTCDate("2100-01-01 00:00:00 UTC");
secretKeys = PGPainless.modifyKeyRing(secretKeys)
.setExpirationDate(notSoFarAwayExpiration, protector)
.done();
Date actualExpiration = PGPainless.inspectKeyRing(secretKeys)
.getPrimaryKeyExpirationDate();
JUtils.assertDateEquals(notSoFarAwayExpiration, actualExpiration);
}
}