View Javadoc
1   /*
2    * Copyright 2018 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty5.handler.ssl;
17  
18  import io.netty.internal.tcnative.SSL;
19  import io.netty5.util.AbstractReferenceCounted;
20  import io.netty5.util.IllegalReferenceCountException;
21  import io.netty5.util.internal.EmptyArrays;
22  
23  import javax.security.auth.Destroyable;
24  import java.security.PrivateKey;
25  import java.security.cert.X509Certificate;
26  
27  final class OpenSslPrivateKey extends AbstractReferenceCounted implements PrivateKey {
28  
29      private long privateKeyAddress;
30  
31      OpenSslPrivateKey(long privateKeyAddress) {
32          this.privateKeyAddress = privateKeyAddress;
33      }
34  
35      @Override
36      public String getAlgorithm() {
37          return "unknown";
38      }
39  
40      @Override
41      public String getFormat() {
42          // As we do not support encoding we should return null as stated in the javadocs of PrivateKey.
43          return null;
44      }
45  
46      @Override
47      public byte[] getEncoded() {
48          return null;
49      }
50  
51      private long privateKeyAddress() {
52          if (refCnt() <= 0) {
53              throw new IllegalReferenceCountException();
54          }
55          return privateKeyAddress;
56      }
57  
58      @Override
59      protected void deallocate() {
60          SSL.freePrivateKey(privateKeyAddress);
61          privateKeyAddress = 0;
62      }
63  
64      @Override
65      public OpenSslPrivateKey retain() {
66          super.retain();
67          return this;
68      }
69  
70      @Override
71      public OpenSslPrivateKey retain(int increment) {
72          super.retain(increment);
73          return this;
74      }
75  
76      @Override
77      public OpenSslPrivateKey touch() {
78          super.touch();
79          return this;
80      }
81  
82      @Override
83      public OpenSslPrivateKey touch(Object hint) {
84          return this;
85      }
86  
87      /**
88       * NOTE: This is a JDK8 interface/method. Due to backwards compatibility
89       * reasons it's not possible to slap the {@code @Override} annotation onto
90       * this method.
91       *
92       * @see Destroyable#destroy()
93       */
94      @Override
95      public void destroy() {
96          release(refCnt());
97      }
98  
99      /**
100      * NOTE: This is a JDK8 interface/method. Due to backwards compatibility
101      * reasons it's not possible to slap the {@code @Override} annotation onto
102      * this method.
103      *
104      * @see Destroyable#isDestroyed()
105      */
106     @Override
107     public boolean isDestroyed() {
108         return refCnt() == 0;
109     }
110 
111     /**
112      * Create a new {@link OpenSslKeyMaterial} which uses the private key that is held by {@link OpenSslPrivateKey}.
113      *
114      * When the material is created we increment the reference count of the enclosing {@link OpenSslPrivateKey} and
115      * decrement it again when the reference count of the {@link OpenSslKeyMaterial} reaches {@code 0}.
116      */
117     OpenSslKeyMaterial newKeyMaterial(long certificateChain, X509Certificate[] chain) {
118         return new OpenSslPrivateKeyMaterial(certificateChain, chain);
119     }
120 
121     // Package-private for unit-test only
122     final class OpenSslPrivateKeyMaterial extends AbstractReferenceCounted implements OpenSslKeyMaterial {
123 
124         // Package-private for unit-test only
125         long certificateChain;
126         private final X509Certificate[] x509CertificateChain;
127 
128         OpenSslPrivateKeyMaterial(long certificateChain, X509Certificate[] x509CertificateChain) {
129             this.certificateChain = certificateChain;
130             this.x509CertificateChain = x509CertificateChain == null ?
131                     EmptyArrays.EMPTY_X509_CERTIFICATES : x509CertificateChain;
132             OpenSslPrivateKey.this.retain();
133         }
134 
135         @Override
136         public X509Certificate[] certificateChain() {
137             return x509CertificateChain.clone();
138         }
139 
140         @Override
141         public long certificateChainAddress() {
142             if (refCnt() <= 0) {
143                 throw new IllegalReferenceCountException();
144             }
145             return certificateChain;
146         }
147 
148         @Override
149         public long privateKeyAddress() {
150             if (refCnt() <= 0) {
151                 throw new IllegalReferenceCountException();
152             }
153             return OpenSslPrivateKey.this.privateKeyAddress();
154         }
155 
156         @Override
157         public OpenSslKeyMaterial touch(Object hint) {
158             OpenSslPrivateKey.this.touch(hint);
159             return this;
160         }
161 
162         @Override
163         public OpenSslKeyMaterial retain() {
164             super.retain();
165             return this;
166         }
167 
168         @Override
169         public OpenSslKeyMaterial retain(int increment) {
170             super.retain(increment);
171             return this;
172         }
173 
174         @Override
175         public OpenSslKeyMaterial touch() {
176             OpenSslPrivateKey.this.touch();
177             return this;
178         }
179 
180         @Override
181         protected void deallocate() {
182             releaseChain();
183             OpenSslPrivateKey.this.release();
184         }
185 
186         private void releaseChain() {
187             SSL.freeX509Chain(certificateChain);
188             certificateChain = 0;
189         }
190     }
191 }