|
1 | 1 | /* |
2 | | - * Copyright (c) 2017 The Netty Project |
3 | 2 | * Copyright (c) 2020-2021 Estonian Information System Authority |
4 | 3 | * |
5 | | - * The Netty Project and The Web eID Project license this file to you under the |
6 | | - * Apache License, version 2.0 (the "License"); you may not use this file except |
7 | | - * in compliance with the License. You may obtain a copy of the License at: |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 5 | + * of this software and associated documentation files (the "Software"), to deal |
| 6 | + * in the Software without restriction, including without limitation the rights |
| 7 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 8 | + * copies of the Software, and to permit persons to whom the Software is |
| 9 | + * furnished to do so, subject to the following conditions: |
8 | 10 | * |
9 | | - * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + * The above copyright notice and this permission notice shall be included in all |
| 12 | + * copies or substantial portions of the Software. |
10 | 13 | * |
11 | | - * Unless required by applicable law or agreed to in writing, software |
12 | | - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
13 | | - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
14 | | - * License for the specific language governing permissions and limitations under |
15 | | - * the License. |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 17 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 19 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 20 | + * SOFTWARE. |
16 | 21 | */ |
17 | 22 |
|
18 | 23 | package org.webeid.security.validator.ocsp; |
19 | 24 |
|
20 | | -import org.bouncycastle.asn1.ASN1Encodable; |
21 | | -import org.bouncycastle.asn1.ASN1ObjectIdentifier; |
22 | | -import org.bouncycastle.asn1.ASN1Primitive; |
23 | | -import org.bouncycastle.asn1.BERTags; |
24 | | -import org.bouncycastle.asn1.DLSequence; |
25 | | -import org.bouncycastle.asn1.DLTaggedObject; |
26 | | -import org.bouncycastle.asn1.x509.Extension; |
27 | | -import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; |
| 25 | +import org.bouncycastle.asn1.ASN1String; |
| 26 | +import org.bouncycastle.asn1.x509.AccessDescription; |
| 27 | +import org.bouncycastle.asn1.x509.AuthorityInformationAccess; |
| 28 | +import org.bouncycastle.asn1.x509.GeneralName; |
| 29 | +import org.bouncycastle.cert.X509CertificateHolder; |
28 | 30 |
|
29 | 31 | import java.io.IOException; |
30 | 32 | import java.net.URI; |
31 | | -import java.nio.charset.StandardCharsets; |
| 33 | +import java.security.cert.CertificateEncodingException; |
32 | 34 | import java.security.cert.X509Certificate; |
33 | 35 | import java.util.Objects; |
34 | 36 |
|
35 | 37 | public final class OcspUrl { |
36 | 38 |
|
37 | 39 | public static final URI AIA_ESTEID_2015 = URI.create("http://aia.sk.ee/esteid2015"); |
38 | 40 |
|
39 | | - /** |
40 | | - * The OID for OCSP responder URLs. |
41 | | - * <p> |
42 | | - * https://oidref.com/1.3.6.1.5.5.7.48.1 |
43 | | - */ |
44 | | - private static final ASN1ObjectIdentifier OCSP_RESPONDER_OID |
45 | | - = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1").intern(); |
46 | | - |
47 | 41 | /** |
48 | 42 | * Returns the OCSP responder {@link URI} or {@code null} if it doesn't have one. |
49 | 43 | */ |
50 | 44 | public static URI getOcspUri(X509Certificate certificate) { |
51 | 45 | Objects.requireNonNull(certificate, "certificate"); |
52 | | - final byte[] value = certificate.getExtensionValue(Extension.authorityInfoAccess.getId()); |
53 | | - if (value == null) { |
54 | | - return null; |
55 | | - } |
56 | | - |
57 | | - final ASN1Primitive authorityInfoAccess; |
| 46 | + final X509CertificateHolder certificateHolder; |
58 | 47 | try { |
59 | | - authorityInfoAccess = JcaX509ExtensionUtils.parseExtensionValue(value); |
60 | | - } catch (IOException | IllegalArgumentException e) { |
61 | | - return null; |
62 | | - } |
63 | | - if (!(authorityInfoAccess instanceof DLSequence)) { |
64 | | - return null; |
65 | | - } |
66 | | - |
67 | | - final DLSequence aiaSequence = (DLSequence) authorityInfoAccess; |
68 | | - final DLTaggedObject taggedObject = findObject(aiaSequence, OCSP_RESPONDER_OID, DLTaggedObject.class); |
69 | | - if (taggedObject == null) { |
70 | | - return null; |
71 | | - } |
72 | | - |
73 | | - if (taggedObject.getTagNo() != BERTags.OBJECT_IDENTIFIER) { |
74 | | - return null; |
75 | | - } |
76 | | - |
77 | | - final byte[] encoded; |
78 | | - try { |
79 | | - encoded = taggedObject.getEncoded(); |
80 | | - } catch (IOException e) { |
81 | | - return null; |
82 | | - } |
83 | | - int length = encoded[1] & 0xFF; |
84 | | - final String uri = new String(encoded, 2, length, StandardCharsets.UTF_8); |
85 | | - return URI.create(uri); |
86 | | - } |
87 | | - |
88 | | - private static <T> T findObject(DLSequence sequence, ASN1ObjectIdentifier oid, Class<T> type) { |
89 | | - for (final ASN1Encodable element : sequence) { |
90 | | - if (!(element instanceof DLSequence)) { |
91 | | - continue; |
92 | | - } |
93 | | - |
94 | | - final DLSequence subSequence = (DLSequence) element; |
95 | | - if (subSequence.size() != 2) { |
96 | | - continue; |
97 | | - } |
98 | | - |
99 | | - final ASN1Encodable key = subSequence.getObjectAt(0); |
100 | | - final ASN1Encodable value = subSequence.getObjectAt(1); |
101 | | - |
102 | | - if (key.equals(oid) && type.isInstance(value)) { |
103 | | - return type.cast(value); |
| 48 | + certificateHolder = new X509CertificateHolder(certificate.getEncoded()); |
| 49 | + final AuthorityInformationAccess authorityInformationAccess = |
| 50 | + AuthorityInformationAccess.fromExtensions(certificateHolder.getExtensions()); |
| 51 | + for (AccessDescription accessDescription : |
| 52 | + authorityInformationAccess.getAccessDescriptions()) { |
| 53 | + if (accessDescription.getAccessMethod().equals(AccessDescription.id_ad_ocsp) && |
| 54 | + accessDescription.getAccessLocation().getTagNo() == GeneralName.uniformResourceIdentifier) { |
| 55 | + final String accessLocationUrl = ((ASN1String) accessDescription.getAccessLocation().getName()) |
| 56 | + .getString(); |
| 57 | + return URI.create(accessLocationUrl); |
| 58 | + } |
104 | 59 | } |
| 60 | + } catch (IOException | CertificateEncodingException | IllegalArgumentException | NullPointerException e) { |
| 61 | + return null; |
105 | 62 | } |
106 | | - |
107 | 63 | return null; |
108 | 64 | } |
109 | 65 |
|
|
0 commit comments