001 /* Copyright (c) 2002 Graz University of Technology. All rights reserved.
002 *
003 * Redistribution and use in source and binary forms, with or without
004 * modification, are permitted provided that the following conditions are met:
005 *
006 * 1. Redistributions of source code must retain the above copyright notice,
007 * this list of conditions and the following disclaimer.
008 *
009 * 2. Redistributions in binary form must reproduce the above copyright notice,
010 * this list of conditions and the following disclaimer in the documentation
011 * and/or other materials provided with the distribution.
012 *
013 * 3. The end-user documentation included with the redistribution, if any, must
014 * include the following acknowledgment:
015 *
016 * "This product includes software developed by IAIK of Graz University of
017 * Technology."
018 *
019 * Alternately, this acknowledgment may appear in the software itself, if
020 * and wherever such third-party acknowledgments normally appear.
021 *
022 * 4. The names "Graz University of Technology" and "IAIK of Graz University of
023 * Technology" must not be used to endorse or promote products derived from
024 * this software without prior written permission.
025 *
026 * 5. Products derived from this software may not be called
027 * "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
028 * written permission of Graz University of Technology.
029 *
030 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
031 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
032 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
033 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
034 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
035 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
036 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
037 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
038 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
039 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
040 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
041 * POSSIBILITY OF SUCH DAMAGE.
042 */
043
044 package demo.pkcs.pkcs11;
045
046 import java.security.InvalidKeyException;
047 import java.security.InvalidParameterException;
048 import java.security.MessageDigest;
049 import java.security.NoSuchAlgorithmException;
050 import java.security.Signature;
051 import java.security.SignatureException;
052
053 import iaik.asn1.structures.AlgorithmID;
054 import iaik.pkcs.pkcs11.Mechanism;
055 import iaik.pkcs.pkcs11.Session;
056 import iaik.pkcs.pkcs11.TokenException;
057 import iaik.pkcs.pkcs11.objects.Key;
058 import iaik.pkcs.pkcs7.DigestInfo;
059
060
061
062 /**
063 * This is an implementation of a JCA Signature class that uses the PKCS#11
064 * wrapper to create the signature. This implementation hashes outside the
065 * token (i.e. in software) and support only signing but not verification.
066 *
067 * @author <a href="mailto:Karl.Scheibelhofer@iaik.at"> Karl Scheibelhofer </a>
068 * @version 0.1
069 * @invariants
070 */
071 public class PKCS11SignatureEngine extends Signature {
072
073 /**
074 * The session that this object uses for signing with the token.
075 */
076 protected Session session_;
077
078 /**
079 * The mechanism that this object uses for signing with the token.
080 */
081 protected Mechanism signatureMechanism_;
082
083 /**
084 * The PKCS#11 key that this object uses for signing with the token.
085 */
086 protected Key signatureKey_;
087
088 /**
089 * The hash algorithm to use for hashing the data.
090 */
091 protected AlgorithmID hashAlgorithm_;
092
093 /**
094 * The digest engine used to hash the data.
095 */
096 protected MessageDigest digestEngine_;
097
098 /**
099 * Creates a new signature engine that uses the given parameters to create
100 * the signature on the PKCS#11 token.
101 *
102 * @param algorithmName The name of the signature algorithm. This class does
103 * not interpret this name; it uses it as is.
104 * @param session The PKCS#11 session to use for signing. It must have the
105 * permissions to sign with the used private key; e.g. it may
106 * require a user session.
107 * @param signatureMechanism The PKCS#11 mechanism to use for signing; e.g.
108 * Mechanism.RSA_PKCS.
109 * @param hashAlgorithm The hash algorithm to use for hashing the data;
110 * e.g. AlgorithmID.sha1.
111 * @exception NoSuchAlgorithmException If the hash algorithm is not available.
112 * @preconditions
113 * @postconditions
114 */
115 public PKCS11SignatureEngine(String algorithmName, Session session, Mechanism signatureMechanism,
116 AlgorithmID hashAlgorithm)
117 throws NoSuchAlgorithmException
118 {
119 super(algorithmName);
120 session_ = session;
121 signatureMechanism_ = signatureMechanism;
122 hashAlgorithm_ = hashAlgorithm;
123 // we do digesting outside the card, because some cards do not support on-card hashing
124 digestEngine_ = hashAlgorithm_.getMessageDigestInstance();
125 }
126
127 /**
128 * SPI: see documentation of java.security.Signature.
129 */
130 protected boolean engineVerify(byte[] signatureValue)
131 throws SignatureException
132 {
133 throw new UnsupportedOperationException();
134 }
135
136 /**
137 * SPI: see documentation of java.security.Signature.
138 */
139 protected java.lang.Object engineGetParameter(String name)
140 throws InvalidParameterException
141 {
142 throw new UnsupportedOperationException();
143 }
144
145 /**
146 * SPI: see documentation of java.security.Signature.
147 */
148 protected void engineSetParameter(String param, java.lang.Object value)
149 throws InvalidParameterException
150 {
151 throw new UnsupportedOperationException();
152 }
153
154 /**
155 * SPI: see documentation of java.security.Signature.
156 */
157 protected void engineInitSign(java.security.PrivateKey privateKey)
158 throws InvalidKeyException
159 {
160 if (!(privateKey instanceof TokenPrivateKey)) {
161 throw new InvalidKeyException("Private key must be of instance InvalidKeyException");
162 }
163 signatureKey_ = ((TokenPrivateKey) privateKey).getTokenPrivateKey();
164 }
165
166 /**
167 * SPI: see documentation of java.security.Signature.
168 */
169 protected byte[] engineSign()
170 throws SignatureException
171 {
172 byte[] hashToBeSigned = digestEngine_.digest();
173
174 // according to PKCS#11 building the DigestInfo structure must be done off-card
175 DigestInfo digestInfoEngine = new DigestInfo(AlgorithmID.sha1, hashToBeSigned);
176
177 byte[] toBeEncrypted = digestInfoEngine.toByteArray();
178
179 byte[] signatureValue = null;
180 try {
181 // initialize for signing
182 session_.signInit(signatureMechanism_, signatureKey_);
183
184 // sign the data to be signed
185 signatureValue = session_.sign(toBeEncrypted);
186 } catch (TokenException ex) {
187 throw new SignatureException(ex.toString());
188 }
189
190 return signatureValue ;
191 }
192
193 /**
194 * SPI: see documentation of java.security.Signature.
195 */
196 protected void engineInitVerify(java.security.PublicKey publicKey)
197 throws InvalidKeyException
198 {
199 throw new UnsupportedOperationException();
200 }
201
202 /**
203 * SPI: see documentation of java.security.Signature.
204 */
205 protected void engineUpdate(byte dataByte)
206 throws SignatureException
207 {
208 digestEngine_.update(dataByte);
209 }
210
211 /**
212 * SPI: see documentation of java.security.Signature.
213 */
214 protected void engineUpdate(byte[] data, int offset, int length)
215 throws SignatureException
216 {
217 digestEngine_.update(data, offset, length);
218 }
219
220 }