author | ascarpino |
Wed, 08 Feb 2017 12:08:28 -0800 | |
changeset 43701 | fe8c324ba97c |
parent 41590 | 1c5b1891b8e0 |
child 45992 | 38bdf44057b9 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
43701
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
2 |
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.security.pkcs; |
|
27 |
||
28 |
import java.io.OutputStream; |
|
29 |
import java.io.IOException; |
|
30 |
import java.math.BigInteger; |
|
41580 | 31 |
import java.security.CryptoPrimitive; |
32 |
import java.security.InvalidKeyException; |
|
33 |
import java.security.MessageDigest; |
|
34 |
import java.security.NoSuchAlgorithmException; |
|
35 |
import java.security.Principal; |
|
36 |
import java.security.PublicKey; |
|
37 |
import java.security.Signature; |
|
38 |
import java.security.SignatureException; |
|
39 |
import java.security.Timestamp; |
|
43701
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
40 |
import java.security.cert.CertPathValidatorException; |
10788
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
41 |
import java.security.cert.CertificateException; |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
42 |
import java.security.cert.CertificateFactory; |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
43 |
import java.security.cert.CertPath; |
2 | 44 |
import java.security.cert.X509Certificate; |
45 |
import java.util.ArrayList; |
|
18224 | 46 |
import java.util.Arrays; |
41580 | 47 |
import java.util.Collections; |
48 |
import java.util.EnumSet; |
|
49 |
import java.util.Set; |
|
2 | 50 |
|
10788
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
51 |
import sun.security.timestamp.TimestampToken; |
43701
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
52 |
import sun.security.util.ConstraintsParameters; |
41580 | 53 |
import sun.security.util.Debug; |
54 |
import sun.security.util.DerEncoder; |
|
55 |
import sun.security.util.DerInputStream; |
|
56 |
import sun.security.util.DerOutputStream; |
|
57 |
import sun.security.util.DerValue; |
|
58 |
import sun.security.util.DisabledAlgorithmConstraints; |
|
59 |
import sun.security.util.HexDumpEncoder; |
|
41582
246512d81eba
8165816: jarsigner -verify shows jar unsigned if it was signed with a weak algorithm
weijun
parents:
41580
diff
changeset
|
60 |
import sun.security.util.KeyUtil; |
41580 | 61 |
import sun.security.util.ObjectIdentifier; |
2 | 62 |
import sun.security.x509.AlgorithmId; |
63 |
import sun.security.x509.X500Name; |
|
64 |
import sun.security.x509.KeyUsageExtension; |
|
65 |
||
66 |
/** |
|
67 |
* A SignerInfo, as defined in PKCS#7's signedData type. |
|
68 |
* |
|
69 |
* @author Benjamin Renaud |
|
70 |
*/ |
|
71 |
public class SignerInfo implements DerEncoder { |
|
72 |
||
41580 | 73 |
// Digest and Signature restrictions |
74 |
private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = |
|
75 |
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST)); |
|
76 |
||
77 |
private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = |
|
78 |
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); |
|
79 |
||
80 |
private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK = |
|
81 |
new DisabledAlgorithmConstraints( |
|
82 |
DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS); |
|
83 |
||
2 | 84 |
BigInteger version; |
85 |
X500Name issuerName; |
|
86 |
BigInteger certificateSerialNumber; |
|
87 |
AlgorithmId digestAlgorithmId; |
|
88 |
AlgorithmId digestEncryptionAlgorithmId; |
|
89 |
byte[] encryptedDigest; |
|
10788
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
90 |
Timestamp timestamp; |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
91 |
private boolean hasTimestamp = true; |
18224 | 92 |
private static final Debug debug = Debug.getInstance("jar"); |
2 | 93 |
|
94 |
PKCS9Attributes authenticatedAttributes; |
|
95 |
PKCS9Attributes unauthenticatedAttributes; |
|
96 |
||
97 |
public SignerInfo(X500Name issuerName, |
|
98 |
BigInteger serial, |
|
99 |
AlgorithmId digestAlgorithmId, |
|
100 |
AlgorithmId digestEncryptionAlgorithmId, |
|
101 |
byte[] encryptedDigest) { |
|
102 |
this.version = BigInteger.ONE; |
|
103 |
this.issuerName = issuerName; |
|
104 |
this.certificateSerialNumber = serial; |
|
105 |
this.digestAlgorithmId = digestAlgorithmId; |
|
106 |
this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId; |
|
107 |
this.encryptedDigest = encryptedDigest; |
|
108 |
} |
|
109 |
||
110 |
public SignerInfo(X500Name issuerName, |
|
111 |
BigInteger serial, |
|
112 |
AlgorithmId digestAlgorithmId, |
|
113 |
PKCS9Attributes authenticatedAttributes, |
|
114 |
AlgorithmId digestEncryptionAlgorithmId, |
|
115 |
byte[] encryptedDigest, |
|
116 |
PKCS9Attributes unauthenticatedAttributes) { |
|
117 |
this.version = BigInteger.ONE; |
|
118 |
this.issuerName = issuerName; |
|
119 |
this.certificateSerialNumber = serial; |
|
120 |
this.digestAlgorithmId = digestAlgorithmId; |
|
121 |
this.authenticatedAttributes = authenticatedAttributes; |
|
122 |
this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId; |
|
123 |
this.encryptedDigest = encryptedDigest; |
|
124 |
this.unauthenticatedAttributes = unauthenticatedAttributes; |
|
125 |
} |
|
126 |
||
127 |
/** |
|
128 |
* Parses a PKCS#7 signer info. |
|
129 |
*/ |
|
130 |
public SignerInfo(DerInputStream derin) |
|
131 |
throws IOException, ParsingException |
|
132 |
{ |
|
133 |
this(derin, false); |
|
134 |
} |
|
135 |
||
136 |
/** |
|
137 |
* Parses a PKCS#7 signer info. |
|
138 |
* |
|
139 |
* <p>This constructor is used only for backwards compatibility with |
|
140 |
* PKCS#7 blocks that were generated using JDK1.1.x. |
|
141 |
* |
|
142 |
* @param derin the ASN.1 encoding of the signer info. |
|
143 |
* @param oldStyle flag indicating whether or not the given signer info |
|
144 |
* is encoded according to JDK1.1.x. |
|
145 |
*/ |
|
146 |
public SignerInfo(DerInputStream derin, boolean oldStyle) |
|
147 |
throws IOException, ParsingException |
|
148 |
{ |
|
149 |
// version |
|
150 |
version = derin.getBigInteger(); |
|
151 |
||
152 |
// issuerAndSerialNumber |
|
153 |
DerValue[] issuerAndSerialNumber = derin.getSequence(2); |
|
154 |
byte[] issuerBytes = issuerAndSerialNumber[0].toByteArray(); |
|
155 |
issuerName = new X500Name(new DerValue(DerValue.tag_Sequence, |
|
156 |
issuerBytes)); |
|
157 |
certificateSerialNumber = issuerAndSerialNumber[1].getBigInteger(); |
|
158 |
||
159 |
// digestAlgorithmId |
|
160 |
DerValue tmp = derin.getDerValue(); |
|
161 |
||
162 |
digestAlgorithmId = AlgorithmId.parse(tmp); |
|
163 |
||
164 |
// authenticatedAttributes |
|
165 |
if (oldStyle) { |
|
166 |
// In JDK1.1.x, the authenticatedAttributes are always present, |
|
167 |
// encoded as an empty Set (Set of length zero) |
|
168 |
derin.getSet(0); |
|
169 |
} else { |
|
170 |
// check if set of auth attributes (implicit tag) is provided |
|
171 |
// (auth attributes are OPTIONAL) |
|
172 |
if ((byte)(derin.peekByte()) == (byte)0xA0) { |
|
173 |
authenticatedAttributes = new PKCS9Attributes(derin); |
|
174 |
} |
|
175 |
} |
|
176 |
||
177 |
// digestEncryptionAlgorithmId - little RSA naming scheme - |
|
178 |
// signature == encryption... |
|
179 |
tmp = derin.getDerValue(); |
|
180 |
||
181 |
digestEncryptionAlgorithmId = AlgorithmId.parse(tmp); |
|
182 |
||
183 |
// encryptedDigest |
|
184 |
encryptedDigest = derin.getOctetString(); |
|
185 |
||
186 |
// unauthenticatedAttributes |
|
187 |
if (oldStyle) { |
|
188 |
// In JDK1.1.x, the unauthenticatedAttributes are always present, |
|
189 |
// encoded as an empty Set (Set of length zero) |
|
190 |
derin.getSet(0); |
|
191 |
} else { |
|
192 |
// check if set of unauth attributes (implicit tag) is provided |
|
193 |
// (unauth attributes are OPTIONAL) |
|
194 |
if (derin.available() != 0 |
|
195 |
&& (byte)(derin.peekByte()) == (byte)0xA1) { |
|
196 |
unauthenticatedAttributes = |
|
197 |
new PKCS9Attributes(derin, true);// ignore unsupported attrs |
|
198 |
} |
|
199 |
} |
|
200 |
||
201 |
// all done |
|
202 |
if (derin.available() != 0) { |
|
203 |
throw new ParsingException("extra data at the end"); |
|
204 |
} |
|
205 |
} |
|
206 |
||
207 |
public void encode(DerOutputStream out) throws IOException { |
|
208 |
||
209 |
derEncode(out); |
|
210 |
} |
|
211 |
||
212 |
/** |
|
213 |
* DER encode this object onto an output stream. |
|
32275
17eeb583a331
8133802: replace some <tt> tags (obsolete in html5) in security-libs docs
avstepan
parents:
31426
diff
changeset
|
214 |
* Implements the {@code DerEncoder} interface. |
2 | 215 |
* |
216 |
* @param out |
|
217 |
* the output stream on which to write the DER encoding. |
|
218 |
* |
|
219 |
* @exception IOException on encoding error. |
|
220 |
*/ |
|
221 |
public void derEncode(OutputStream out) throws IOException { |
|
222 |
DerOutputStream seq = new DerOutputStream(); |
|
223 |
seq.putInteger(version); |
|
224 |
DerOutputStream issuerAndSerialNumber = new DerOutputStream(); |
|
225 |
issuerName.encode(issuerAndSerialNumber); |
|
226 |
issuerAndSerialNumber.putInteger(certificateSerialNumber); |
|
227 |
seq.write(DerValue.tag_Sequence, issuerAndSerialNumber); |
|
228 |
||
229 |
digestAlgorithmId.encode(seq); |
|
230 |
||
231 |
// encode authenticated attributes if there are any |
|
232 |
if (authenticatedAttributes != null) |
|
233 |
authenticatedAttributes.encode((byte)0xA0, seq); |
|
234 |
||
235 |
digestEncryptionAlgorithmId.encode(seq); |
|
236 |
||
237 |
seq.putOctetString(encryptedDigest); |
|
238 |
||
239 |
// encode unauthenticated attributes if there are any |
|
240 |
if (unauthenticatedAttributes != null) |
|
241 |
unauthenticatedAttributes.encode((byte)0xA1, seq); |
|
242 |
||
243 |
DerOutputStream tmp = new DerOutputStream(); |
|
244 |
tmp.write(DerValue.tag_Sequence, seq); |
|
245 |
||
246 |
out.write(tmp.toByteArray()); |
|
247 |
} |
|
248 |
||
249 |
||
250 |
||
251 |
/* |
|
252 |
* Returns the (user) certificate pertaining to this SignerInfo. |
|
253 |
*/ |
|
254 |
public X509Certificate getCertificate(PKCS7 block) |
|
255 |
throws IOException |
|
256 |
{ |
|
257 |
return block.getCertificate(certificateSerialNumber, issuerName); |
|
258 |
} |
|
259 |
||
260 |
/* |
|
261 |
* Returns the certificate chain pertaining to this SignerInfo. |
|
262 |
*/ |
|
263 |
public ArrayList<X509Certificate> getCertificateChain(PKCS7 block) |
|
264 |
throws IOException |
|
265 |
{ |
|
266 |
X509Certificate userCert; |
|
267 |
userCert = block.getCertificate(certificateSerialNumber, issuerName); |
|
268 |
if (userCert == null) |
|
269 |
return null; |
|
270 |
||
30033
b9c86c17164a
8078468: Update security libraries to use diamond with anonymous classes
darcy
parents:
25859
diff
changeset
|
271 |
ArrayList<X509Certificate> certList = new ArrayList<>(); |
2 | 272 |
certList.add(userCert); |
273 |
||
274 |
X509Certificate[] pkcsCerts = block.getCertificates(); |
|
275 |
if (pkcsCerts == null |
|
276 |
|| userCert.getSubjectDN().equals(userCert.getIssuerDN())) { |
|
277 |
return certList; |
|
278 |
} |
|
279 |
||
280 |
Principal issuer = userCert.getIssuerDN(); |
|
281 |
int start = 0; |
|
282 |
while (true) { |
|
283 |
boolean match = false; |
|
284 |
int i = start; |
|
285 |
while (i < pkcsCerts.length) { |
|
286 |
if (issuer.equals(pkcsCerts[i].getSubjectDN())) { |
|
287 |
// next cert in chain found |
|
288 |
certList.add(pkcsCerts[i]); |
|
289 |
// if selected cert is self-signed, we're done |
|
290 |
// constructing the chain |
|
291 |
if (pkcsCerts[i].getSubjectDN().equals( |
|
292 |
pkcsCerts[i].getIssuerDN())) { |
|
293 |
start = pkcsCerts.length; |
|
294 |
} else { |
|
295 |
issuer = pkcsCerts[i].getIssuerDN(); |
|
296 |
X509Certificate tmpCert = pkcsCerts[start]; |
|
297 |
pkcsCerts[start] = pkcsCerts[i]; |
|
298 |
pkcsCerts[i] = tmpCert; |
|
299 |
start++; |
|
300 |
} |
|
301 |
match = true; |
|
302 |
break; |
|
303 |
} else { |
|
304 |
i++; |
|
305 |
} |
|
306 |
} |
|
307 |
if (!match) |
|
308 |
break; |
|
309 |
} |
|
310 |
||
311 |
return certList; |
|
312 |
} |
|
313 |
||
314 |
/* Returns null if verify fails, this signerInfo if |
|
315 |
verify succeeds. */ |
|
316 |
SignerInfo verify(PKCS7 block, byte[] data) |
|
9365 | 317 |
throws NoSuchAlgorithmException, SignatureException { |
318 |
||
319 |
try { |
|
320 |
||
321 |
ContentInfo content = block.getContentInfo(); |
|
322 |
if (data == null) { |
|
323 |
data = content.getContentBytes(); |
|
324 |
} |
|
325 |
||
43701
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
326 |
ConstraintsParameters cparams = |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
327 |
new ConstraintsParameters(timestamp); |
9365 | 328 |
String digestAlgname = getDigestAlgorithmId().getName(); |
329 |
||
330 |
byte[] dataSigned; |
|
331 |
||
332 |
// if there are authenticate attributes, get the message |
|
333 |
// digest and compare it with the digest of data |
|
334 |
if (authenticatedAttributes == null) { |
|
335 |
dataSigned = data; |
|
336 |
} else { |
|
337 |
||
338 |
// first, check content type |
|
339 |
ObjectIdentifier contentType = (ObjectIdentifier) |
|
340 |
authenticatedAttributes.getAttributeValue( |
|
341 |
PKCS9Attribute.CONTENT_TYPE_OID); |
|
342 |
if (contentType == null || |
|
31426
9cd672654f97
8022444: Remove sun.security.util.ObjectIdentifier.equals(ObjectIdentifier other) method
juh
parents:
30033
diff
changeset
|
343 |
!contentType.equals(content.contentType)) |
9365 | 344 |
return null; // contentType does not match, bad SignerInfo |
345 |
||
346 |
// now, check message digest |
|
347 |
byte[] messageDigest = (byte[]) |
|
348 |
authenticatedAttributes.getAttributeValue( |
|
349 |
PKCS9Attribute.MESSAGE_DIGEST_OID); |
|
350 |
||
351 |
if (messageDigest == null) // fail if there is no message digest |
|
352 |
return null; |
|
353 |
||
43701
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
354 |
// check that digest algorithm is not restricted |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
355 |
try { |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
356 |
JAR_DISABLED_CHECK.permits(digestAlgname, cparams); |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
357 |
} catch (CertPathValidatorException e) { |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
358 |
throw new SignatureException(e.getMessage(), e); |
41580 | 359 |
} |
360 |
||
9365 | 361 |
MessageDigest md = MessageDigest.getInstance(digestAlgname); |
362 |
byte[] computedMessageDigest = md.digest(data); |
|
363 |
||
364 |
if (messageDigest.length != computedMessageDigest.length) |
|
365 |
return null; |
|
366 |
for (int i = 0; i < messageDigest.length; i++) { |
|
367 |
if (messageDigest[i] != computedMessageDigest[i]) |
|
368 |
return null; |
|
369 |
} |
|
370 |
||
371 |
// message digest attribute matched |
|
372 |
// digest of original data |
|
373 |
||
374 |
// the data actually signed is the DER encoding of |
|
375 |
// the authenticated attributes (tagged with |
|
376 |
// the "SET OF" tag, not 0xA0). |
|
377 |
dataSigned = authenticatedAttributes.getDerEncoding(); |
|
378 |
} |
|
379 |
||
380 |
// put together digest algorithm and encryption algorithm |
|
381 |
// to form signing algorithm |
|
382 |
String encryptionAlgname = |
|
383 |
getDigestEncryptionAlgorithmId().getName(); |
|
2 | 384 |
|
9365 | 385 |
// Workaround: sometimes the encryptionAlgname is actually |
386 |
// a signature name |
|
387 |
String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname); |
|
388 |
if (tmp != null) encryptionAlgname = tmp; |
|
389 |
String algname = AlgorithmId.makeSigAlg( |
|
390 |
digestAlgname, encryptionAlgname); |
|
391 |
||
43701
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
392 |
// check that jar signature algorithm is not restricted |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
393 |
try { |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
394 |
JAR_DISABLED_CHECK.permits(algname, cparams); |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
395 |
} catch (CertPathValidatorException e) { |
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
396 |
throw new SignatureException(e.getMessage(), e); |
41580 | 397 |
} |
398 |
||
9365 | 399 |
X509Certificate cert = getCertificate(block); |
400 |
if (cert == null) { |
|
401 |
return null; |
|
402 |
} |
|
43701
fe8c324ba97c
8160655: Fix denyAfter and usage types for security properties
ascarpino
parents:
41590
diff
changeset
|
403 |
PublicKey key = cert.getPublicKey(); |
41580 | 404 |
|
405 |
// check if the public key is restricted |
|
406 |
if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { |
|
407 |
throw new SignatureException("Public key check failed. " + |
|
41582
246512d81eba
8165816: jarsigner -verify shows jar unsigned if it was signed with a weak algorithm
weijun
parents:
41580
diff
changeset
|
408 |
"Disabled key used: " + |
246512d81eba
8165816: jarsigner -verify shows jar unsigned if it was signed with a weak algorithm
weijun
parents:
41580
diff
changeset
|
409 |
KeyUtil.getKeySize(key) + " bit " + |
246512d81eba
8165816: jarsigner -verify shows jar unsigned if it was signed with a weak algorithm
weijun
parents:
41580
diff
changeset
|
410 |
key.getAlgorithm()); |
41580 | 411 |
} |
412 |
||
9365 | 413 |
if (cert.hasUnsupportedCriticalExtension()) { |
414 |
throw new SignatureException("Certificate has unsupported " |
|
415 |
+ "critical extension(s)"); |
|
2 | 416 |
} |
9365 | 417 |
|
418 |
// Make sure that if the usage of the key in the certificate is |
|
419 |
// restricted, it can be used for digital signatures. |
|
420 |
// XXX We may want to check for additional extensions in the |
|
421 |
// future. |
|
422 |
boolean[] keyUsageBits = cert.getKeyUsage(); |
|
423 |
if (keyUsageBits != null) { |
|
424 |
KeyUsageExtension keyUsage; |
|
425 |
try { |
|
426 |
// We don't care whether or not this extension was marked |
|
427 |
// critical in the certificate. |
|
428 |
// We're interested only in its value (i.e., the bits set) |
|
429 |
// and treat the extension as critical. |
|
430 |
keyUsage = new KeyUsageExtension(keyUsageBits); |
|
431 |
} catch (IOException ioe) { |
|
432 |
throw new SignatureException("Failed to parse keyUsage " |
|
433 |
+ "extension"); |
|
434 |
} |
|
435 |
||
10336
0bb1999251f8
7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents:
9365
diff
changeset
|
436 |
boolean digSigAllowed = keyUsage.get( |
0bb1999251f8
7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents:
9365
diff
changeset
|
437 |
KeyUsageExtension.DIGITAL_SIGNATURE).booleanValue(); |
9365 | 438 |
|
10336
0bb1999251f8
7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents:
9365
diff
changeset
|
439 |
boolean nonRepuAllowed = keyUsage.get( |
0bb1999251f8
7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents:
9365
diff
changeset
|
440 |
KeyUsageExtension.NON_REPUDIATION).booleanValue(); |
9365 | 441 |
|
442 |
if (!digSigAllowed && !nonRepuAllowed) { |
|
443 |
throw new SignatureException("Key usage restricted: " |
|
444 |
+ "cannot be used for " |
|
445 |
+ "digital signatures"); |
|
446 |
} |
|
447 |
} |
|
448 |
||
41580 | 449 |
Signature sig = Signature.getInstance(algname); |
9365 | 450 |
sig.initVerify(key); |
451 |
sig.update(dataSigned); |
|
452 |
if (sig.verify(encryptedDigest)) { |
|
453 |
return this; |
|
454 |
} |
|
455 |
||
456 |
} catch (IOException e) { |
|
457 |
throw new SignatureException("IO error verifying signature:\n" + |
|
458 |
e.getMessage()); |
|
459 |
||
460 |
} catch (InvalidKeyException e) { |
|
461 |
throw new SignatureException("InvalidKey: " + e.getMessage()); |
|
462 |
||
2 | 463 |
} |
9365 | 464 |
return null; |
2 | 465 |
} |
466 |
||
467 |
/* Verify the content of the pkcs7 block. */ |
|
468 |
SignerInfo verify(PKCS7 block) |
|
469 |
throws NoSuchAlgorithmException, SignatureException { |
|
470 |
return verify(block, null); |
|
471 |
} |
|
472 |
||
473 |
||
474 |
public BigInteger getVersion() { |
|
475 |
return version; |
|
476 |
} |
|
477 |
||
478 |
public X500Name getIssuerName() { |
|
479 |
return issuerName; |
|
480 |
} |
|
481 |
||
482 |
public BigInteger getCertificateSerialNumber() { |
|
483 |
return certificateSerialNumber; |
|
484 |
} |
|
485 |
||
486 |
public AlgorithmId getDigestAlgorithmId() { |
|
487 |
return digestAlgorithmId; |
|
488 |
} |
|
489 |
||
490 |
public PKCS9Attributes getAuthenticatedAttributes() { |
|
491 |
return authenticatedAttributes; |
|
492 |
} |
|
493 |
||
494 |
public AlgorithmId getDigestEncryptionAlgorithmId() { |
|
495 |
return digestEncryptionAlgorithmId; |
|
496 |
} |
|
497 |
||
498 |
public byte[] getEncryptedDigest() { |
|
499 |
return encryptedDigest; |
|
500 |
} |
|
501 |
||
502 |
public PKCS9Attributes getUnauthenticatedAttributes() { |
|
503 |
return unauthenticatedAttributes; |
|
504 |
} |
|
505 |
||
41590
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
506 |
/** |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
507 |
* Returns the timestamp PKCS7 data unverified. |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
508 |
* @return a PKCS7 object |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
509 |
*/ |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
510 |
public PKCS7 getTsToken() throws IOException { |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
511 |
if (unauthenticatedAttributes == null) { |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
512 |
return null; |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
513 |
} |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
514 |
PKCS9Attribute tsTokenAttr = |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
515 |
unauthenticatedAttributes.getAttribute( |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
516 |
PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID); |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
517 |
if (tsTokenAttr == null) { |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
518 |
return null; |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
519 |
} |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
520 |
return new PKCS7((byte[])tsTokenAttr.getValue()); |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
521 |
} |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
522 |
|
10788
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
523 |
/* |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
524 |
* Extracts a timestamp from a PKCS7 SignerInfo. |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
525 |
* |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
526 |
* Examines the signer's unsigned attributes for a |
32275
17eeb583a331
8133802: replace some <tt> tags (obsolete in html5) in security-libs docs
avstepan
parents:
31426
diff
changeset
|
527 |
* {@code signatureTimestampToken} attribute. If present, |
10788
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
528 |
* then it is parsed to extract the date and time at which the |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
529 |
* timestamp was generated. |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
530 |
* |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
531 |
* @param info A signer information element of a PKCS 7 block. |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
532 |
* |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
533 |
* @return A timestamp token or null if none is present. |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
534 |
* @throws IOException if an error is encountered while parsing the |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
535 |
* PKCS7 data. |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
536 |
* @throws NoSuchAlgorithmException if an error is encountered while |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
537 |
* verifying the PKCS7 object. |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
538 |
* @throws SignatureException if an error is encountered while |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
539 |
* verifying the PKCS7 object. |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
540 |
* @throws CertificateException if an error is encountered while generating |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
541 |
* the TSA's certpath. |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
542 |
*/ |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
543 |
public Timestamp getTimestamp() |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
544 |
throws IOException, NoSuchAlgorithmException, SignatureException, |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
545 |
CertificateException |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
546 |
{ |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
547 |
if (timestamp != null || !hasTimestamp) |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
548 |
return timestamp; |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
549 |
|
41590
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
550 |
PKCS7 tsToken = getTsToken(); |
1c5b1891b8e0
8163304: jarsigner -verbose -verify should print the algorithms used to sign the jar
weijun
parents:
41582
diff
changeset
|
551 |
if (tsToken == null) { |
10788
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
552 |
hasTimestamp = false; |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
553 |
return null; |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
554 |
} |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
555 |
|
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
556 |
// Extract the content (an encoded timestamp token info) |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
557 |
byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
558 |
// Extract the signer (the Timestamping Authority) |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
559 |
// while verifying the content |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
560 |
SignerInfo[] tsa = tsToken.verify(encTsTokenInfo); |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
561 |
// Expect only one signer |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
562 |
ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(tsToken); |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
563 |
CertificateFactory cf = CertificateFactory.getInstance("X.509"); |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
564 |
CertPath tsaChain = cf.generateCertPath(chain); |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
565 |
// Create a timestamp token info object |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
566 |
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo); |
18224 | 567 |
// Check that the signature timestamp applies to this signature |
568 |
verifyTimestamp(tsTokenInfo); |
|
10788
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
569 |
// Create a timestamp object |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
570 |
timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain); |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
571 |
return timestamp; |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
572 |
} |
680a3dbfcaba
7102686: Restructure timestamp code so that jars and modules can more easily share the same code
mullan
parents:
10336
diff
changeset
|
573 |
|
18224 | 574 |
/* |
575 |
* Check that the signature timestamp applies to this signature. |
|
576 |
* Match the hash present in the signature timestamp token against the hash |
|
577 |
* of this signature. |
|
578 |
*/ |
|
579 |
private void verifyTimestamp(TimestampToken token) |
|
580 |
throws NoSuchAlgorithmException, SignatureException { |
|
41580 | 581 |
String digestAlgname = token.getHashAlgorithm().getName(); |
582 |
// check that algorithm is not restricted |
|
583 |
if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, digestAlgname, |
|
584 |
null)) { |
|
585 |
throw new SignatureException("Timestamp token digest check failed. " + |
|
586 |
"Disabled algorithm used: " + digestAlgname); |
|
587 |
} |
|
18224 | 588 |
|
589 |
MessageDigest md = |
|
41580 | 590 |
MessageDigest.getInstance(digestAlgname); |
18224 | 591 |
|
592 |
if (!Arrays.equals(token.getHashedMessage(), |
|
593 |
md.digest(encryptedDigest))) { |
|
594 |
||
595 |
throw new SignatureException("Signature timestamp (#" + |
|
596 |
token.getSerialNumber() + ") generated on " + token.getDate() + |
|
597 |
" is inapplicable"); |
|
598 |
} |
|
599 |
||
600 |
if (debug != null) { |
|
601 |
debug.println(); |
|
602 |
debug.println("Detected signature timestamp (#" + |
|
603 |
token.getSerialNumber() + ") generated on " + token.getDate()); |
|
604 |
debug.println(); |
|
605 |
} |
|
606 |
} |
|
607 |
||
2 | 608 |
public String toString() { |
609 |
HexDumpEncoder hexDump = new HexDumpEncoder(); |
|
610 |
||
611 |
String out = ""; |
|
612 |
||
613 |
out += "Signer Info for (issuer): " + issuerName + "\n"; |
|
614 |
out += "\tversion: " + Debug.toHexString(version) + "\n"; |
|
615 |
out += "\tcertificateSerialNumber: " + |
|
616 |
Debug.toHexString(certificateSerialNumber) + "\n"; |
|
617 |
out += "\tdigestAlgorithmId: " + digestAlgorithmId + "\n"; |
|
618 |
if (authenticatedAttributes != null) { |
|
619 |
out += "\tauthenticatedAttributes: " + authenticatedAttributes + |
|
620 |
"\n"; |
|
621 |
} |
|
622 |
out += "\tdigestEncryptionAlgorithmId: " + digestEncryptionAlgorithmId + |
|
623 |
"\n"; |
|
624 |
||
625 |
out += "\tencryptedDigest: " + "\n" + |
|
626 |
hexDump.encodeBuffer(encryptedDigest) + "\n"; |
|
627 |
if (unauthenticatedAttributes != null) { |
|
628 |
out += "\tunauthenticatedAttributes: " + |
|
629 |
unauthenticatedAttributes + "\n"; |
|
630 |
} |
|
631 |
return out; |
|
632 |
} |
|
633 |
} |