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 }