Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/security/x509/DistributionPoint.java
41159 views
1
/*
2
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
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
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
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
*
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.
24
*/
25
26
package sun.security.x509;
27
28
import java.io.IOException;
29
import java.util.*;
30
31
import sun.security.util.BitArray;
32
import sun.security.util.DerOutputStream;
33
import sun.security.util.DerValue;
34
35
/**
36
* Represent the DistributionPoint sequence used in the CRL
37
* Distribution Points Extension (OID = 2.5.29.31).
38
* <p>
39
* The ASN.1 definition for this is:
40
* <pre>
41
* DistributionPoint ::= SEQUENCE {
42
* distributionPoint [0] DistributionPointName OPTIONAL,
43
* reasons [1] ReasonFlags OPTIONAL,
44
* cRLIssuer [2] GeneralNames OPTIONAL }
45
*
46
* DistributionPointName ::= CHOICE {
47
* fullName [0] GeneralNames,
48
* nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
49
*
50
* ReasonFlags ::= BIT STRING {
51
* unused (0),
52
* keyCompromise (1),
53
* cACompromise (2),
54
* affiliationChanged (3),
55
* superseded (4),
56
* cessationOfOperation (5),
57
* certificateHold (6),
58
* privilegeWithdrawn (7),
59
* aACompromise (8) }
60
*
61
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
62
*
63
* GeneralName ::= CHOICE {
64
* otherName [0] INSTANCE OF OTHER-NAME,
65
* rfc822Name [1] IA5String,
66
* dNSName [2] IA5String,
67
* x400Address [3] ORAddress,
68
* directoryName [4] Name,
69
* ediPartyName [5] EDIPartyName,
70
* uniformResourceIdentifier [6] IA5String,
71
* iPAddress [7] OCTET STRING,
72
* registeredID [8] OBJECT IDENTIFIER }
73
*
74
* RelativeDistinguishedName ::=
75
* SET OF AttributeTypeAndValue
76
*
77
* AttributeTypeAndValue ::= SEQUENCE {
78
* type AttributeType,
79
* value AttributeValue }
80
*
81
* AttributeType ::= OBJECT IDENTIFIER
82
*
83
* AttributeValue ::= ANY DEFINED BY AttributeType
84
* </pre>
85
* <p>
86
* Instances of this class are designed to be immutable. However, since this
87
* is an internal API we do not use defensive cloning for values for
88
* performance reasons. It is the responsibility of the consumer to ensure
89
* that no mutable elements are modified.
90
*
91
* @author Anne Anderson
92
* @author Andreas Sterbenz
93
* @since 1.4.2
94
* @see CRLDistributionPointsExtension
95
*/
96
public class DistributionPoint {
97
98
// reason flag bits
99
// NOTE that these are NOT quite the same as the CRL reason code extension
100
public static final int KEY_COMPROMISE = 1;
101
public static final int CA_COMPROMISE = 2;
102
public static final int AFFILIATION_CHANGED = 3;
103
public static final int SUPERSEDED = 4;
104
public static final int CESSATION_OF_OPERATION = 5;
105
public static final int CERTIFICATE_HOLD = 6;
106
public static final int PRIVILEGE_WITHDRAWN = 7;
107
public static final int AA_COMPROMISE = 8;
108
109
private static final String[] REASON_STRINGS = {
110
null,
111
"key compromise",
112
"CA compromise",
113
"affiliation changed",
114
"superseded",
115
"cessation of operation",
116
"certificate hold",
117
"privilege withdrawn",
118
"AA compromise",
119
};
120
121
// context specific tag values
122
private static final byte TAG_DIST_PT = 0;
123
private static final byte TAG_REASONS = 1;
124
private static final byte TAG_ISSUER = 2;
125
126
private static final byte TAG_FULL_NAME = 0;
127
private static final byte TAG_REL_NAME = 1;
128
129
// only one of fullName and relativeName can be set
130
private GeneralNames fullName;
131
private RDN relativeName;
132
133
// reasonFlags or null
134
private boolean[] reasonFlags;
135
136
// crlIssuer or null
137
private GeneralNames crlIssuer;
138
139
// cached hashCode value
140
private volatile int hashCode;
141
142
/**
143
* Constructor for the class using GeneralNames for DistributionPointName
144
*
145
* @param fullName the GeneralNames of the distribution point; may be null
146
* @param reasonFlags the CRL reasons included in the CRL at this distribution
147
* point; may be null
148
* @param crlIssuer the name(s) of the CRL issuer for the CRL at this
149
* distribution point; may be null
150
*/
151
public DistributionPoint(GeneralNames fullName, boolean[] reasonFlags,
152
GeneralNames crlIssuer) {
153
if ((fullName == null) && (crlIssuer == null)) {
154
throw new IllegalArgumentException
155
("fullName and crlIssuer may not both be null");
156
}
157
this.fullName = fullName;
158
this.reasonFlags = reasonFlags;
159
this.crlIssuer = crlIssuer;
160
}
161
162
/**
163
* Constructor for the class using RelativeDistinguishedName for
164
* DistributionPointName
165
*
166
* @param relativeName the RelativeDistinguishedName of the distribution
167
* point; may not be null
168
* @param reasonFlags the CRL reasons included in the CRL at this distribution
169
* point; may be null
170
* @param crlIssuer the name(s) of the CRL issuer for the CRL at this
171
* distribution point; may not be null or empty.
172
*/
173
public DistributionPoint(RDN relativeName, boolean[] reasonFlags,
174
GeneralNames crlIssuer) {
175
if ((relativeName == null) && (crlIssuer == null)) {
176
throw new IllegalArgumentException
177
("relativeName and crlIssuer may not both be null");
178
}
179
this.relativeName = relativeName;
180
this.reasonFlags = reasonFlags;
181
this.crlIssuer = crlIssuer;
182
}
183
184
/**
185
* Create the object from the passed DER encoded form.
186
*
187
* @param val the DER encoded form of the DistributionPoint
188
* @throws IOException on error
189
*/
190
public DistributionPoint(DerValue val) throws IOException {
191
if (val.tag != DerValue.tag_Sequence) {
192
throw new IOException("Invalid encoding of DistributionPoint.");
193
}
194
195
// Note that all the fields in DistributionPoint are defined as
196
// being OPTIONAL, i.e., there could be an empty SEQUENCE, resulting
197
// in val.data being null.
198
while ((val.data != null) && (val.data.available() != 0)) {
199
DerValue opt = val.data.getDerValue();
200
201
if (opt.isContextSpecific(TAG_DIST_PT) && opt.isConstructed()) {
202
if ((fullName != null) || (relativeName != null)) {
203
throw new IOException("Duplicate DistributionPointName in "
204
+ "DistributionPoint.");
205
}
206
DerValue distPnt = opt.data.getDerValue();
207
if (distPnt.isContextSpecific(TAG_FULL_NAME)
208
&& distPnt.isConstructed()) {
209
distPnt.resetTag(DerValue.tag_Sequence);
210
fullName = new GeneralNames(distPnt);
211
} else if (distPnt.isContextSpecific(TAG_REL_NAME)
212
&& distPnt.isConstructed()) {
213
distPnt.resetTag(DerValue.tag_Set);
214
relativeName = new RDN(distPnt);
215
} else {
216
throw new IOException("Invalid DistributionPointName in "
217
+ "DistributionPoint");
218
}
219
} else if (opt.isContextSpecific(TAG_REASONS)
220
&& !opt.isConstructed()) {
221
if (reasonFlags != null) {
222
throw new IOException("Duplicate Reasons in " +
223
"DistributionPoint.");
224
}
225
opt.resetTag(DerValue.tag_BitString);
226
reasonFlags = (opt.getUnalignedBitString()).toBooleanArray();
227
} else if (opt.isContextSpecific(TAG_ISSUER)
228
&& opt.isConstructed()) {
229
if (crlIssuer != null) {
230
throw new IOException("Duplicate CRLIssuer in " +
231
"DistributionPoint.");
232
}
233
opt.resetTag(DerValue.tag_Sequence);
234
crlIssuer = new GeneralNames(opt);
235
} else {
236
throw new IOException("Invalid encoding of " +
237
"DistributionPoint.");
238
}
239
}
240
if ((crlIssuer == null) && (fullName == null) && (relativeName == null)) {
241
throw new IOException("One of fullName, relativeName, "
242
+ " and crlIssuer has to be set");
243
}
244
}
245
246
/**
247
* Return the full distribution point name or null if not set.
248
*/
249
public GeneralNames getFullName() {
250
return fullName;
251
}
252
253
/**
254
* Return the relative distribution point name or null if not set.
255
*/
256
public RDN getRelativeName() {
257
return relativeName;
258
}
259
260
/**
261
* Return the reason flags or null if not set.
262
*/
263
public boolean[] getReasonFlags() {
264
return reasonFlags;
265
}
266
267
/**
268
* Return the CRL issuer name or null if not set.
269
*/
270
public GeneralNames getCRLIssuer() {
271
return crlIssuer;
272
}
273
274
/**
275
* Write the DistributionPoint value to the DerOutputStream.
276
*
277
* @param out the DerOutputStream to write the extension to.
278
* @exception IOException on error.
279
*/
280
public void encode(DerOutputStream out) throws IOException {
281
DerOutputStream tagged = new DerOutputStream();
282
283
// NOTE: only one of pointNames and pointRDN can be set
284
if ((fullName != null) || (relativeName != null)) {
285
DerOutputStream distributionPoint = new DerOutputStream();
286
if (fullName != null) {
287
DerOutputStream derOut = new DerOutputStream();
288
fullName.encode(derOut);
289
distributionPoint.writeImplicit(
290
DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_FULL_NAME),
291
derOut);
292
} else if (relativeName != null) {
293
DerOutputStream derOut = new DerOutputStream();
294
relativeName.encode(derOut);
295
distributionPoint.writeImplicit(
296
DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_REL_NAME),
297
derOut);
298
}
299
tagged.write(
300
DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_DIST_PT),
301
distributionPoint);
302
}
303
if (reasonFlags != null) {
304
DerOutputStream reasons = new DerOutputStream();
305
BitArray rf = new BitArray(reasonFlags);
306
reasons.putTruncatedUnalignedBitString(rf);
307
tagged.writeImplicit(
308
DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_REASONS),
309
reasons);
310
}
311
if (crlIssuer != null) {
312
DerOutputStream issuer = new DerOutputStream();
313
crlIssuer.encode(issuer);
314
tagged.writeImplicit(
315
DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_ISSUER),
316
issuer);
317
}
318
out.write(DerValue.tag_Sequence, tagged);
319
}
320
321
/**
322
* Compare an object to this DistributionPoint for equality.
323
*
324
* @param obj Object to be compared to this
325
* @return true if objects match; false otherwise
326
*/
327
public boolean equals(Object obj) {
328
if (this == obj) {
329
return true;
330
}
331
if (obj instanceof DistributionPoint == false) {
332
return false;
333
}
334
DistributionPoint other = (DistributionPoint)obj;
335
336
boolean equal = Objects.equals(this.fullName, other.fullName)
337
&& Objects.equals(this.relativeName, other.relativeName)
338
&& Objects.equals(this.crlIssuer, other.crlIssuer)
339
&& Arrays.equals(this.reasonFlags, other.reasonFlags);
340
return equal;
341
}
342
343
public int hashCode() {
344
int hash = hashCode;
345
if (hash == 0) {
346
hash = 1;
347
if (fullName != null) {
348
hash += fullName.hashCode();
349
}
350
if (relativeName != null) {
351
hash += relativeName.hashCode();
352
}
353
if (crlIssuer != null) {
354
hash += crlIssuer.hashCode();
355
}
356
if (reasonFlags != null) {
357
for (int i = 0; i < reasonFlags.length; i++) {
358
if (reasonFlags[i]) {
359
hash += i;
360
}
361
}
362
}
363
hashCode = hash;
364
}
365
return hash;
366
}
367
368
/**
369
* Return a string representation for reasonFlag bit 'reason'.
370
*/
371
private static String reasonToString(int reason) {
372
if ((reason > 0) && (reason < REASON_STRINGS.length)) {
373
return REASON_STRINGS[reason];
374
}
375
return "Unknown reason " + reason;
376
}
377
378
/**
379
* Return a printable string of the Distribution Point.
380
*/
381
public String toString() {
382
StringBuilder sb = new StringBuilder();
383
sb.append("DistributionPoint:\n ");
384
if (fullName != null) {
385
sb.append(fullName);
386
}
387
if (relativeName != null) {
388
sb.append(relativeName);
389
}
390
sb.append('\n');
391
392
if (reasonFlags != null) {
393
sb.append(" ReasonFlags:\n");
394
for (int i = 0; i < reasonFlags.length; i++) {
395
if (reasonFlags[i]) {
396
sb.append(" ")
397
.append(reasonToString(i))
398
.append('\n');
399
}
400
}
401
}
402
if (crlIssuer != null) {
403
sb.append(" CRLIssuer:")
404
.append(crlIssuer)
405
.append('\n');
406
}
407
return sb.toString();
408
}
409
410
}
411
412