• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 package software.amazon.awssdk.crt.io;
6 
7 import java.util.HashMap;
8 import java.util.Map;
9 import java.io.StringWriter;
10 import java.io.PrintWriter;
11 
12 import software.amazon.awssdk.crt.CrtResource;
13 import software.amazon.awssdk.crt.Log;
14 import software.amazon.awssdk.crt.Log.LogLevel;
15 import software.amazon.awssdk.crt.Log.LogSubject;
16 
17 /**
18  * A class containing a mutual TLS (mTLS) Private Key operation that needs to be performed.
19  * This class is passed to TlsKeyOperationHandler if a custom key operation is set.
20  *
21  * You MUST call either complete(output) or completeExceptionally(exception)
22  * or the TLS connection will hang forever!
23  */
24 public final class TlsKeyOperation {
25 
26     /**
27      * The type of TlsKeyOperation that needs to be performed by the TlsKeyOperationHandler interface.
28      */
29     public enum Type {
30         UNKNOWN(0), SIGN(1), DECRYPT(2);
31 
buildEnumMapping()32         static Map<Integer, Type> buildEnumMapping() {
33             Map<Integer, Type> enumMapping = new HashMap<Integer, Type>();
34             for (Type i : Type.values()) {
35                 enumMapping.put(i.nativeValue, i);
36             }
37             return enumMapping;
38         }
39 
getEnumValueFromInteger(int value)40         public static Type getEnumValueFromInteger(int value) {
41             Type enumValue = enumMapping.get(value);
42             if (enumValue != null) {
43                 return enumValue;
44             }
45             throw new RuntimeException("Illegal TlsKeyOperation.Type");
46         }
47 
Type(int nativeValue)48         Type(int nativeValue) {
49             this.nativeValue = nativeValue;
50         }
51 
getNativeValue()52         public int getNativeValue() {
53             return nativeValue;
54         }
55 
56         int nativeValue;
57         static Map<Integer, Type> enumMapping = buildEnumMapping();
58     }
59 
60     private CrtResourceInternal nativeResource;
61     private byte[] inputData;
62     private Type operationType;
63     private TlsSignatureAlgorithm signatureAlgorithm;
64     private TlsHashAlgorithm digestAlgorithm;
65 
66     /* Called from native when there's a new operation to be performed. Creates a new TlsKeyOperation */
TlsKeyOperation(long nativeHandle, byte[] inputData, int operationType, int signatureAlgorithm, int digestAlgorithm)67     protected TlsKeyOperation(long nativeHandle, byte[] inputData, int operationType, int signatureAlgorithm,
68             int digestAlgorithm) {
69 
70         nativeResource = new CrtResourceInternal(nativeHandle);
71         this.inputData = inputData;
72         this.operationType = Type.getEnumValueFromInteger(operationType);
73         this.signatureAlgorithm = TlsSignatureAlgorithm.getEnumValueFromInteger(signatureAlgorithm);
74         this.digestAlgorithm = TlsHashAlgorithm.getEnumValueFromInteger(digestAlgorithm);
75     }
76 
77     /**
78      * Returns the input data from native that needs to be operated on using the private key.
79      * You can determine the operation that needs to be performed on the data using the getType function.
80      *
81      * @return The input data from native that needs to be operated on
82      */
getInput()83     public byte[] getInput() {
84         return inputData;
85     }
86 
87     /**
88      * Returns the operation that needs to be performed.
89      *
90      * @return The operation that needs to be performed.
91      */
getType()92     public Type getType() {
93         return operationType;
94     }
95 
96     /**
97      * Returns the TLS algorithm used in the signature.
98      *
99      * @return The TLS algorithm used in the signature
100      */
getSignatureAlgorithm()101     public TlsSignatureAlgorithm getSignatureAlgorithm() {
102         return signatureAlgorithm;
103     }
104 
105     /**
106      * Returns the TLS Hash algorithm used in the digest.
107      *
108      * @return The TLS Hash algorithm used in the digest
109      */
getDigestAlgorithm()110     public TlsHashAlgorithm getDigestAlgorithm() {
111         return digestAlgorithm;
112     }
113 
114     /**
115      * The function to call when you have modified the input data using the private key and are ready to
116      * return it for use in the mutual TLS Handshake.
117      *
118      * @param output The modified input data that has been modified by the custom key operation
119      */
complete(byte[] output)120     public synchronized void complete(byte[] output) {
121         if (nativeResource.isNull()) {
122             Log.log(LogLevel.Error, LogSubject.CommonGeneral,
123                 "No native handle set in TlsKeyOperation! Cannot complete operation");
124             return;
125         }
126 
127         tlsKeyOperationComplete(nativeResource.getNativeHandle(), output);
128         nativeResource.close();
129     }
130 
131     /**
132      * The function to call when you either have an exception and want to complete the operation with an
133      * exception or you cannot complete the operation. This will mark the operation as complete with an
134      * exception so it can be reacted to accordingly.
135      *
136      * @param ex The exeception to complete with
137      */
completeExceptionally(Throwable ex)138     public synchronized void completeExceptionally(Throwable ex) {
139         if (nativeResource.isNull()) {
140             Log.log(LogLevel.Error, LogSubject.CommonGeneral,
141                 "No native handle set in TlsKeyOperation! Cannot complete operation exceptionally");
142             return;
143         }
144 
145         tlsKeyOperationCompleteExceptionally(nativeResource.getNativeHandle(), ex);
146         nativeResource.close();
147     }
148 
149     /**
150      * The TlsKeyOperation has special lifetime rules, where you have to call one of the complete functions, and
151      * by using this private, internal-only CRT resource, we can still get the benefits of using a CRT resource
152      * for detecting memory leaks, while not exposing functionality that would conflict with the lifetime rules.
153      */
154     private class CrtResourceInternal extends CrtResource {
CrtResourceInternal(long nativeHandle)155         CrtResourceInternal(long nativeHandle) {
156             acquireNativeHandle(nativeHandle);
157         }
158 
releaseNativeHandle()159         protected void releaseNativeHandle() {}
160 
canReleaseReferencesImmediately()161         protected boolean canReleaseReferencesImmediately() {
162             return true;
163         };
164     }
165 
invokePerformOperation(TlsKeyOperationHandler handler, TlsKeyOperation operation)166     static private void invokePerformOperation(TlsKeyOperationHandler handler, TlsKeyOperation operation) {
167         try {
168             handler.performOperation(operation);
169         } catch (Exception ex) {
170             /**
171              * printStackTrace gives a nice, full picture of the exception
172              * but to use it, we have to use a StringWriter and a PrintWriter
173              */
174             StringWriter stringWriter = new StringWriter();
175             ex.printStackTrace(new PrintWriter(stringWriter));
176             Log.log(LogLevel.Error, LogSubject.CommonGeneral,
177                 "Exception occured!\n" + stringWriter.toString());
178 
179             operation.completeExceptionally(ex);
180         }
181     }
182 
183     /*******************************************************************************
184      * native methods
185      ******************************************************************************/
tlsKeyOperationComplete(long nativeHandle, byte[] output)186     private static native void tlsKeyOperationComplete(long nativeHandle, byte[] output);
tlsKeyOperationCompleteExceptionally(long nativeHandle, Throwable ex)187     private static native void tlsKeyOperationCompleteExceptionally(long nativeHandle, Throwable ex);
188 
189 }
190 
191