| | |
| | | import org.opends.server.util.SelectableCertificateKeyManager; |
| | | import org.opends.server.util.StaticUtils; |
| | | import org.opends.server.util.Base64; |
| | | import static org.opends.server.util.ServerConstants.OC_TOP; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.schema.DirectoryStringSyntax; |
| | |
| | | private static final DebugTracer TRACER = getTracer(); |
| | | |
| | | // Various schema element references. |
| | | private final AttributeType attrKeyID; |
| | | private final AttributeType attrPublicKeyCertificate; |
| | | private final AttributeType attrTransformation; |
| | | private final AttributeType attrMacAlgorithm; |
| | | private final AttributeType attrSymmetricKey; |
| | | private final AttributeType attrInitVectorLength; |
| | | private final AttributeType attrKeyLength; |
| | | private final AttributeType attrCompromisedTime; |
| | | private final ObjectClass ocCipherKey; |
| | | private final ObjectClass ocMacKey; |
| | | private static AttributeType attrKeyID; |
| | | private static AttributeType attrPublicKeyCertificate; |
| | | private static AttributeType attrTransformation; |
| | | private static AttributeType attrMacAlgorithm; |
| | | private static AttributeType attrSymmetricKey; |
| | | private static AttributeType attrInitVectorLength; |
| | | private static AttributeType attrKeyLength; |
| | | private static AttributeType attrCompromisedTime; |
| | | private static ObjectClass ocCipherKey; |
| | | private static ObjectClass ocMacKey; |
| | | |
| | | // The DN of the administration suffix. |
| | | private static DN adminSuffixDN; |
| | | |
| | | // The DN of the ADS secret keys container. |
| | | private static DN secretKeysDN; |
| | | |
| | | // Indicates whether the schema references have been initialized. |
| | | private static boolean schemaInitDone = false; |
| | | |
| | | // The secure random number generator used for key generation, |
| | | // initialization vector PRNG seed... |
| | |
| | | // The set of SSL cipher suites enabled or null for the default set. |
| | | private final SortedSet<String> sslCipherSuites; |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this crypto manager object from a given |
| | | * configuration. |
| | |
| | | public CryptoManager(CryptoManagerCfg cfg) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | if (!schemaInitDone) |
| | | { |
| | | // Initialize various schema references. |
| | | attrKeyID = DirectoryServer.getAttributeType( |
| | | ConfigConstants.ATTR_CRYPTO_KEY_ID); |
| | |
| | | ocMacKey = DirectoryServer.getObjectClass( |
| | | ConfigConstants.OC_CRYPTO_MAC_KEY); |
| | | |
| | | try |
| | | { |
| | | adminSuffixDN = DN.decode( |
| | | ADSContext.getAdministrationSuffixDN()); |
| | | secretKeysDN = adminSuffixDN.concat( |
| | | DN.decode("cn=secret keys")); |
| | | } |
| | | catch (DirectoryException e) |
| | | { |
| | | throw new InitializationException(e.getMessageObject()); |
| | | } |
| | | |
| | | schemaInitDone = true; |
| | | } |
| | | |
| | | // TODO -- Get the crypto defaults from the configuration. |
| | | |
| | | // Preferred digest and validation. |
| | |
| | | (null == iv) ? 0 : iv.length * Byte.SIZE); |
| | | |
| | | if (null != map) { |
| | | publishKeyEntry(cryptoManager, keyEntry); |
| | | map.put(keyEntry.getKeyID(), keyEntry); |
| | | // TODO: publish key in ADS. (mark key "blocked" in map |
| | | // TODO: (mark key "blocked" in map |
| | | // until registered? OTOH, Key should be in local map prior to |
| | | // publication, since data could arrive from a remote OpenDS |
| | | // instance encrypted with the key any time after publication. |
| | |
| | | |
| | | |
| | | /** |
| | | * Publish a new cipher key by adding an entry into ADS. |
| | | * @param cryptoManager The CryptoManager instance for which the |
| | | * key was generated. |
| | | * @param keyEntry The cipher key to be published. |
| | | * @throws CryptoManagerException |
| | | * If the key entry could not be added to |
| | | * ADS. |
| | | */ |
| | | private static void publishKeyEntry(CryptoManager cryptoManager, |
| | | CipherKeyEntry keyEntry) |
| | | throws CryptoManagerException |
| | | { |
| | | // Construct the key entry DN. |
| | | AttributeValue distinguishedValue = |
| | | new AttributeValue(attrKeyID, |
| | | keyEntry.getKeyID().getStringValue()); |
| | | DN entryDN = secretKeysDN.concat( |
| | | RDN.create(attrKeyID, distinguishedValue)); |
| | | |
| | | // Set the entry object classes. |
| | | LinkedHashMap<ObjectClass,String> ocMap = |
| | | new LinkedHashMap<ObjectClass,String>(2); |
| | | ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP); |
| | | ocMap.put(ocCipherKey, ConfigConstants.OC_CRYPTO_CIPHER_KEY); |
| | | |
| | | // Create the operational and user attributes. |
| | | LinkedHashMap<AttributeType,List<Attribute>> opAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(0); |
| | | LinkedHashMap<AttributeType,List<Attribute>> userAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | // Add the key ID attribute. |
| | | LinkedHashSet<AttributeValue> valueSet = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(distinguishedValue); |
| | | |
| | | ArrayList<Attribute> attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(new Attribute(attrKeyID, |
| | | attrKeyID.getNameOrOID(), |
| | | valueSet)); |
| | | userAttrs.put(attrKeyID, attrList); |
| | | |
| | | // Add the transformation name attribute. |
| | | valueSet = new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(new AttributeValue(attrTransformation, |
| | | keyEntry.getType())); |
| | | |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add( |
| | | new Attribute(attrTransformation, |
| | | attrTransformation.getNameOrOID(), |
| | | valueSet)); |
| | | userAttrs.put(attrTransformation, attrList); |
| | | |
| | | |
| | | // Add the init vector length attribute. |
| | | valueSet = new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(new AttributeValue( |
| | | attrInitVectorLength, |
| | | String.valueOf(keyEntry.getIVLengthBits()))); |
| | | |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add( |
| | | new Attribute(attrInitVectorLength, |
| | | attrInitVectorLength.getNameOrOID(), |
| | | valueSet)); |
| | | userAttrs.put(attrInitVectorLength, attrList); |
| | | |
| | | |
| | | // Add the key length attribute. |
| | | valueSet = new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(new AttributeValue( |
| | | attrKeyLength, |
| | | String.valueOf(keyEntry.getKeyLengthBits()))); |
| | | |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add( |
| | | new Attribute(attrKeyLength, |
| | | attrKeyLength.getNameOrOID(), |
| | | valueSet)); |
| | | userAttrs.put(attrKeyLength, attrList); |
| | | |
| | | |
| | | // Get the trusted certificates. |
| | | Map<String, byte[]> trustedCerts = |
| | | cryptoManager.getTrustedCertificates(); |
| | | |
| | | // Need to add our own instance certificate. |
| | | byte[] instanceKeyCertificate = |
| | | cryptoManager.getInstanceKeyCertificate(); |
| | | trustedCerts.put(getInstanceKeyID(instanceKeyCertificate), |
| | | instanceKeyCertificate); |
| | | |
| | | // Add the symmetric key attribute. |
| | | LinkedHashSet<AttributeValue> symmetricKeyValues = |
| | | new LinkedHashSet<AttributeValue>(trustedCerts.size()); |
| | | |
| | | for (Map.Entry<String, byte[]> mapEntry : |
| | | trustedCerts.entrySet()) |
| | | { |
| | | String symmetricKey = |
| | | cryptoManager.encodeSymmetricKeyAttribute( |
| | | mapEntry.getKey(), |
| | | mapEntry.getValue(), |
| | | keyEntry.getSecretKey()); |
| | | |
| | | symmetricKeyValues.add( |
| | | new AttributeValue(attrSymmetricKey, symmetricKey)); |
| | | |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(new Attribute(attrSymmetricKey, |
| | | attrSymmetricKey.getNameOrOID(), |
| | | symmetricKeyValues)); |
| | | userAttrs.put(attrSymmetricKey, attrList); |
| | | } |
| | | |
| | | // Create the entry. |
| | | Entry entry = new Entry(entryDN, ocMap, userAttrs, opAttrs); |
| | | |
| | | InternalClientConnection connection = |
| | | InternalClientConnection.getRootConnection(); |
| | | AddOperation addOperation = connection.processAdd(entry); |
| | | if (addOperation.getResultCode() != ResultCode.SUCCESS) |
| | | { |
| | | // TODO i18n |
| | | Message message = Message.raw( |
| | | "Unable to add generated cipher key entry %s: %s", |
| | | entry.getDN(), addOperation.getErrorMessage()); |
| | | throw new CryptoManagerException(message); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Initializes a secret key entry from the supplied parameters, |
| | | * validates it, and registers it in the supplied map. The |
| | | * anticipated use of this method is to import a key entry from |
| | |
| | | // Validate new entry. |
| | | byte[] iv = null; |
| | | if (0 < ivLengthBits) { |
| | | iv = new byte[ivLengthBits * Byte.SIZE]; |
| | | iv = new byte[ivLengthBits / Byte.SIZE]; |
| | | pseudoRandom.nextBytes(iv); |
| | | } |
| | | getCipher(keyEntry, Cipher.DECRYPT_MODE, iv); |
| | |
| | | getMacEngine(keyEntry); |
| | | |
| | | if (null != map) { |
| | | publishKeyEntry(cryptoManager, keyEntry); |
| | | map.put(keyEntry.getKeyID(), keyEntry); |
| | | // TODO: publish key in ADS. (mark key "blocked" in map |
| | | // TODO: (mark key "blocked" in map |
| | | // until registered? OTOH, Key should be in local map prior to |
| | | // publication, since data could arrive from a remote OpenDS |
| | | // instance encrypted with the key any time after publication. |
| | |
| | | |
| | | |
| | | /** |
| | | * Publish a new mac key by adding an entry into ADS. |
| | | * @param cryptoManager The CryptoManager instance for which the |
| | | * key was generated. |
| | | * @param keyEntry The mac key to be published. |
| | | * @throws CryptoManagerException |
| | | * If the key entry could not be added to |
| | | * ADS. |
| | | */ |
| | | private static void publishKeyEntry(CryptoManager cryptoManager, |
| | | MacKeyEntry keyEntry) |
| | | throws CryptoManagerException |
| | | { |
| | | // Construct the key entry DN. |
| | | AttributeValue distinguishedValue = |
| | | new AttributeValue(attrKeyID, |
| | | keyEntry.getKeyID().getStringValue()); |
| | | DN entryDN = secretKeysDN.concat( |
| | | RDN.create(attrKeyID, distinguishedValue)); |
| | | |
| | | // Set the entry object classes. |
| | | LinkedHashMap<ObjectClass,String> ocMap = |
| | | new LinkedHashMap<ObjectClass,String>(2); |
| | | ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP); |
| | | ocMap.put(ocMacKey, ConfigConstants.OC_CRYPTO_MAC_KEY); |
| | | |
| | | // Create the operational and user attributes. |
| | | LinkedHashMap<AttributeType,List<Attribute>> opAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(0); |
| | | LinkedHashMap<AttributeType,List<Attribute>> userAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | // Add the key ID attribute. |
| | | LinkedHashSet<AttributeValue> valueSet = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(distinguishedValue); |
| | | |
| | | ArrayList<Attribute> attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(new Attribute(attrKeyID, |
| | | attrKeyID.getNameOrOID(), |
| | | valueSet)); |
| | | userAttrs.put(attrKeyID, attrList); |
| | | |
| | | // Add the mac algorithm name attribute. |
| | | valueSet = new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(new AttributeValue(attrMacAlgorithm, |
| | | keyEntry.getType())); |
| | | |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add( |
| | | new Attribute(attrMacAlgorithm, |
| | | attrMacAlgorithm.getNameOrOID(), |
| | | valueSet)); |
| | | userAttrs.put(attrMacAlgorithm, attrList); |
| | | |
| | | |
| | | // Add the key length attribute. |
| | | valueSet = new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(new AttributeValue( |
| | | attrKeyLength, |
| | | String.valueOf(keyEntry.getKeyLengthBits()))); |
| | | |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add( |
| | | new Attribute(attrKeyLength, |
| | | attrKeyLength.getNameOrOID(), |
| | | valueSet)); |
| | | userAttrs.put(attrKeyLength, attrList); |
| | | |
| | | |
| | | // Get the trusted certificates. |
| | | Map<String, byte[]> trustedCerts = |
| | | cryptoManager.getTrustedCertificates(); |
| | | |
| | | // Need to add our own instance certificate. |
| | | byte[] instanceKeyCertificate = |
| | | cryptoManager.getInstanceKeyCertificate(); |
| | | trustedCerts.put(getInstanceKeyID(instanceKeyCertificate), |
| | | instanceKeyCertificate); |
| | | |
| | | // Add the symmetric key attribute. |
| | | LinkedHashSet<AttributeValue> symmetricKeyValues = |
| | | new LinkedHashSet<AttributeValue>(trustedCerts.size()); |
| | | |
| | | for (Map.Entry<String, byte[]> mapEntry : |
| | | trustedCerts.entrySet()) |
| | | { |
| | | String symmetricKey = |
| | | cryptoManager.encodeSymmetricKeyAttribute( |
| | | mapEntry.getKey(), |
| | | mapEntry.getValue(), |
| | | keyEntry.getSecretKey()); |
| | | |
| | | symmetricKeyValues.add( |
| | | new AttributeValue(attrSymmetricKey, symmetricKey)); |
| | | |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(new Attribute(attrSymmetricKey, |
| | | attrSymmetricKey.getNameOrOID(), |
| | | symmetricKeyValues)); |
| | | userAttrs.put(attrSymmetricKey, attrList); |
| | | } |
| | | |
| | | // Create the entry. |
| | | Entry entry = new Entry(entryDN, ocMap, userAttrs, opAttrs); |
| | | |
| | | InternalClientConnection connection = |
| | | InternalClientConnection.getRootConnection(); |
| | | AddOperation addOperation = connection.processAdd(entry); |
| | | if (addOperation.getResultCode() != ResultCode.SUCCESS) |
| | | { |
| | | // TODO i18n |
| | | Message message = Message.raw( |
| | | "Unable to add generated mac key entry %s: %s", |
| | | entry.getDN(), addOperation.getErrorMessage()); |
| | | throw new CryptoManagerException(message); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Initializes a secret key entry from the supplied parameters, |
| | | * validates it, and registers it in the supplied map. The |
| | | * anticipated use of this method is to import a key entry from |