Skip to content

Commit

Permalink
added DSASigner to the constraint set.
Browse files Browse the repository at this point in the history
refactored CryptoService to CryptoServiceProperties.
added Purpose test and legacy algorithm support to constraints.
  • Loading branch information
dghgit committed Jul 25, 2022
1 parent 05e1c2f commit e767376
Show file tree
Hide file tree
Showing 14 changed files with 442 additions and 52 deletions.
8 changes: 0 additions & 8 deletions core/src/main/java/org/bouncycastle/crypto/CryptoService.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.bouncycastle.crypto;

public interface CryptoServiceProperties
{
enum Purpose
{
ENCRYPTION,
DECRYPTION,
SIGNING,
VERIFYING,
BOTH
}

int bitsOfSecurity();

String getServiceName();

Purpose getPurpose();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public interface CryptoServicesConstraints
{
void check(CryptoService service);
void check(CryptoServiceProperties service);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public SecureRandom get()

private static final CryptoServicesConstraints noConstraintsImpl = new CryptoServicesConstraints()
{
public void check(CryptoService service)
public void check(CryptoServiceProperties service)
{
// anything goes.
}
Expand Down Expand Up @@ -201,7 +201,7 @@ public static CryptoServicesConstraints getServicesConstraints()
* @param cryptoService the service to be checked.
* @throws CryptoServiceConstraintsException if the service violates the current constraints.
*/
public static void checkConstraints(CryptoService cryptoService)
public static void checkConstraints(CryptoServiceProperties cryptoService)
{
servicesConstraints.get().check(cryptoService);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
package org.bouncycastle.crypto.constraints;

import org.bouncycastle.crypto.CryptoService;
import java.util.Collections;
import java.util.Set;

import org.bouncycastle.crypto.CryptoServiceConstraintsException;
import org.bouncycastle.crypto.CryptoServicesConstraints;
import org.bouncycastle.crypto.CryptoServiceProperties;

/**
* Basic bits of security constraint. Anything not of the required bits of security and
* not in the exception list will be rejected.
*/
public class BitsOfSecurityConstraint
implements CryptoServicesConstraints
extends ServicesConstraint
{
private final int requiredBitsOfSecurity;

public BitsOfSecurityConstraint(int requiredBitsOfSecurity)
{
super(Collections.EMPTY_SET);

this.requiredBitsOfSecurity = requiredBitsOfSecurity;
}

public BitsOfSecurityConstraint(int requiredBitsOfSecurity, Set<String> exceptions)
{
super(exceptions);

this.requiredBitsOfSecurity = requiredBitsOfSecurity;
}

public void check(CryptoService service)
public void check(CryptoServiceProperties service)
{
if (isException(service.getServiceName()))
{
return;
}

if (service.bitsOfSecurity() < requiredBitsOfSecurity)
{
throw new CryptoServiceConstraintsException("service does not provide " + requiredBitsOfSecurity + " bits of security only " + service.bitsOfSecurity());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.bouncycastle.crypto.constraints;

import java.util.Collections;
import java.util.Set;
import java.util.logging.Level;

import org.bouncycastle.crypto.CryptoServiceConstraintsException;
import org.bouncycastle.crypto.CryptoServiceProperties;

import static org.bouncycastle.crypto.CryptoServiceProperties.Purpose.BOTH;

/**
* Legacy bits of security constraint. By default, legacy algorithms are all acceptable but can only
* be used for decryption and verification tasks. Algorithms with the required bits of security can be
* used for anything. If a minimum level of security is given for legacy algorithms, then anything below
* that will be treated as an error unless it appears in the exception list.
*/
public class LegacyBitsOfSecurityConstraint
extends ServicesConstraint
{
private final int requiredBitsOfSecurity;
private final int legacyRequiredBitsOfSecurity;

/**
* Base constructor, legacy level is set to 0.
*
* @param requiredBitsOfSecurity required bits of security for encryption and signing operations.
*/
public LegacyBitsOfSecurityConstraint(int requiredBitsOfSecurity)
{
this(requiredBitsOfSecurity, 0);
}

/**
* Provide required bits of security and legacy requirements.
*
* @param requiredBitsOfSecurity required bits of security for encryption and signing operations.
* @param legacyRequiredBitsOfSecurity acceptable bits of security for decryption and verification operations.
*/
public LegacyBitsOfSecurityConstraint(int requiredBitsOfSecurity, int legacyRequiredBitsOfSecurity)
{
super(Collections.EMPTY_SET);

this.requiredBitsOfSecurity = requiredBitsOfSecurity;
this.legacyRequiredBitsOfSecurity = legacyRequiredBitsOfSecurity;
}

/**
* Provide required bits of security, and a set of exceptions. Legacy requirement will default to 0.
*
* @param requiredBitsOfSecurity required bits of security for encryption and signing operations.
* @param exceptions set service names which are exceptions to the above rules.
*/
public LegacyBitsOfSecurityConstraint(int requiredBitsOfSecurity, Set<String> exceptions)
{
this(requiredBitsOfSecurity, 0, exceptions);
}

/**
* Provide required bits of security, legacy requirements, and a set of exceptions.
*
* @param requiredBitsOfSecurity required bits of security for encryption and signing operations.
* @param legacyRequiredBitsOfSecurity acceptable bits of security for decryption and verification operations.
* @param exceptions set service names which are exceptions to the above rules.
*/
public LegacyBitsOfSecurityConstraint(int requiredBitsOfSecurity, int legacyRequiredBitsOfSecurity, Set<String> exceptions)
{
super(exceptions);

this.requiredBitsOfSecurity = requiredBitsOfSecurity;
this.legacyRequiredBitsOfSecurity = legacyRequiredBitsOfSecurity;
}

public void check(CryptoServiceProperties service)
{
if (isException(service.getServiceName()))
{
return;
}

CryptoServiceProperties.Purpose purpose = service.getPurpose();

// BOTH is allowed as we assume verifying/encryption will be blocked later.
switch (purpose)
{
case BOTH:
case VERIFYING:
case DECRYPTION:
if (service.bitsOfSecurity() < legacyRequiredBitsOfSecurity)
{
throw new CryptoServiceConstraintsException("service does not provide " + requiredBitsOfSecurity + " bits of security only " + service.bitsOfSecurity());
}
if (purpose != BOTH && LOG.isLoggable(Level.FINE))
{
LOG.fine("usage of legacy cryptography service for algorithm " + service.getServiceName());
}
return;
}

if (service.bitsOfSecurity() < requiredBitsOfSecurity)
{
throw new CryptoServiceConstraintsException("service does not provide " + requiredBitsOfSecurity + " bits of security only " + service.bitsOfSecurity());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.bouncycastle.crypto.constraints;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Logger;

import org.bouncycastle.crypto.CryptoServicesConstraints;
import org.bouncycastle.util.Strings;

/**
* Base class for a constraint, serves to provide storage for the set of exceptions (if any).
*/
abstract public class ServicesConstraint
implements CryptoServicesConstraints
{
protected static final Logger LOG = Logger.getLogger(ServicesConstraint.class.getName());

private final Set<String> exceptions;

protected ServicesConstraint(Set<String> exceptions)
{
if (exceptions.isEmpty())
{
this.exceptions = Collections.EMPTY_SET;
}
else
{
this.exceptions = new HashSet<>(exceptions.size());
for (Iterator it = exceptions.iterator(); it.hasNext();)
{
this.exceptions.add(Strings.toUpperCase(it.next().toString()));
}

Utils.addAliases(this.exceptions);
}
}

protected boolean isException(String algorithm)
{
if (exceptions.isEmpty())
{
return false;
}

return exceptions.contains(Strings.toUpperCase(algorithm));
}
}
24 changes: 24 additions & 0 deletions core/src/main/java/org/bouncycastle/crypto/constraints/Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.bouncycastle.crypto.constraints;

import java.util.Set;

class Utils
{
/**
* Depending on usage, in some places algorithms are referred to slightly
* differently. We try to sort that out here.
*
* @param exceptions set of exceptions from constraint checking.
*/
static void addAliases(Set<String> exceptions)
{
if (exceptions.contains("RC4"))
{
exceptions.add("ARC4");
}
else if (exceptions.contains("ARC4"))
{
exceptions.add("RC4");
}
}
}
40 changes: 29 additions & 11 deletions core/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoService;
import org.bouncycastle.crypto.CryptoServiceProperties;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.OutputLengthException;
Expand All @@ -14,18 +14,19 @@
*/
public class DESEngine
extends DESBase
implements BlockCipher, CryptoService
implements BlockCipher
{
protected static final int BLOCK_SIZE = 8;

private boolean forEncryption;
private int[] workingKey = null;

/**
* standard constructor.
*/
public DESEngine()
{
CryptoServicesRegistrar.checkConstraints(this);
CryptoServicesRegistrar.checkConstraints(new DefaultProperties());
}

/**
Expand All @@ -46,10 +47,13 @@ public void init(
{
throw new IllegalArgumentException("DES key too long - should be 8 bytes");
}


forEncryption = encrypting;
workingKey = generateWorkingKey(encrypting,
((KeyParameter)params).getKey());

CryptoServicesRegistrar.checkConstraints(new DefaultProperties());

return;
}

Expand Down Expand Up @@ -485,13 +489,27 @@ protected void desFunc(
Pack.intToBigEndian(left, out, outOff + 4);
}

public int bitsOfSecurity()
{
return 56;
}

public String getServiceName()
private class DefaultProperties
implements CryptoServiceProperties
{
return getAlgorithmName();
public int bitsOfSecurity()
{
return 56;
}

public String getServiceName()
{
return getAlgorithmName();
}

public Purpose getPurpose()
{
if (workingKey == null)
{
return Purpose.BOTH;
}

return forEncryption ? Purpose.ENCRYPTION : Purpose.DECRYPTION;
}
}
}
Loading

0 comments on commit e767376

Please sign in to comment.