001 /*
002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org
003 * Copyright (C) 2011 NightLabs Consulting GmbH
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program. If not, see <http://www.gnu.org/licenses/>.
017 */
018 package org.cumulus4j.keymanager.channel;
019
020 import java.io.IOException;
021 import java.security.GeneralSecurityException;
022 import java.util.Collections;
023 import java.util.Date;
024 import java.util.Map;
025 import java.util.WeakHashMap;
026
027 import org.bouncycastle.crypto.CryptoException;
028 import org.cumulus4j.keymanager.Session;
029 import org.cumulus4j.keymanager.SessionManager;
030 import org.cumulus4j.keymanager.back.shared.GetActiveEncryptionKeyRequest;
031 import org.cumulus4j.keymanager.back.shared.GetActiveEncryptionKeyResponse;
032 import org.cumulus4j.keymanager.back.shared.GetKeyResponse;
033 import org.cumulus4j.keymanager.back.shared.KeyEncryptionUtil;
034 import org.cumulus4j.keymanager.back.shared.Response;
035 import org.cumulus4j.keystore.AuthenticationException;
036 import org.cumulus4j.keystore.DateDependentKeyStrategy;
037 import org.cumulus4j.keystore.KeyNotFoundException;
038 import org.cumulus4j.keystore.KeyStore;
039
040 /**
041 * <p>
042 * Handler for {@link GetActiveEncryptionKeyRequest}.
043 * </p>
044 * <p>
045 * If the {@link Session} is found for the given
046 * {@link org.cumulus4j.keymanager.back.shared.Request#getCryptoSessionID() cryptoSessionID} and
047 * it is not {@link Session#isReleased() locked}, this handler determines the currently active
048 * encryption key and sends it in a {@link GetKeyResponse} to the server.
049 * </p>
050 *
051 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
052 */
053 public class GetActiveEncryptionKeyRequestHandler extends AbstractRequestHandler<GetActiveEncryptionKeyRequest>
054 {
055 private static Map<KeyStore, DateDependentKeyStrategy.ActiveKey> keyStore2activeKey = Collections.synchronizedMap(
056 new WeakHashMap<KeyStore, DateDependentKeyStrategy.ActiveKey>()
057 );
058
059 @Override
060 public Response handle(GetActiveEncryptionKeyRequest request)
061 throws AuthenticationException, KeyNotFoundException, IOException, GeneralSecurityException, CryptoException
062 {
063 SessionManager sessionManager = getKeyManagerChannelManager().getSessionManager();
064 Session session = sessionManager.getSessionForCryptoSessionID(request.getCryptoSessionID());
065
066 // TODO typed exceptions/typed responses?!
067 if (session == null)
068 throw new IllegalStateException("There is no session for cryptoSessionID=" + request.getCryptoSessionID() + "!");
069
070 if (session.isReleased())
071 throw new IllegalStateException("The session for cryptoSessionID=" + request.getCryptoSessionID() + " is currently locked!");
072
073 if (session.getExpiry().before(new Date()))
074 throw new IllegalStateException("The session for cryptoSessionID=" + request.getCryptoSessionID() + " is already expired!");
075
076 if (request.getTimestamp() == null)
077 throw new IllegalArgumentException("request.getTimestamp() == null");
078
079 KeyStore keyStore = sessionManager.getKeyStore();
080 DateDependentKeyStrategy.ActiveKey currentActiveKey = keyStore2activeKey.get(keyStore);
081
082 if (currentActiveKey == null || currentActiveKey.getActiveToExcl().compareTo(request.getTimestamp()) <= 0) {
083 DateDependentKeyStrategy keyStrategy = new DateDependentKeyStrategy(keyStore);
084 DateDependentKeyStrategy.ActiveKey newActiveKey = keyStrategy.getActiveKey(
085 session.getUserName(), session.getPassword(), request.getTimestamp()
086 );
087 if (newActiveKey == null)
088 throw new IllegalStateException("keyStrategy.getActiveKey(...) returned null!");
089
090 keyStore2activeKey.put(keyStore, newActiveKey);
091 currentActiveKey = newActiveKey;
092 }
093
094 byte[] key = keyStore.getKey(session.getUserName(), session.getPassword(), currentActiveKey.getKeyID());
095 byte[] keyEncodedEncrypted = KeyEncryptionUtil.encryptKey(key, request.getKeyEncryptionTransformation(), request.getKeyEncryptionPublicKey());
096 return new GetActiveEncryptionKeyResponse(
097 request,
098 currentActiveKey.getKeyID(), keyEncodedEncrypted, currentActiveKey.getActiveToExcl()
099 );
100 }
101
102 }