1 /* 2 * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 package software.amazon.awssdk.crt.cal; 16 17 import software.amazon.awssdk.crt.auth.credentials.Credentials; 18 import software.amazon.awssdk.crt.CrtResource; 19 20 import java.util.HashMap; 21 import java.util.Map; 22 23 /** 24 * This class puts an opaque wrapper around aws_ecc_key_pair from aws-c-cal. Currently, it is only intended to be 25 * cached and returned to native code by a signing invocation. 26 * 27 * If there's a compelling reason, we can add accessors and conversions to/from Java's KeyPair. 28 */ 29 public final class EccKeyPair extends CrtResource { 30 31 /** 32 * Enum for supported ECC curves 33 * Needs to stay in sync with aws_ecc_curve_name 34 */ 35 public enum AwsEccCurve { 36 /** Nist standard P256 elliptic curve */ 37 AWS_ECDSA_P256(0), 38 39 /** Nist standard P384 elliptic curve */ 40 AWS_ECDSA_P384(1); 41 42 /** 43 * Constructs a Java enum value from a native enum value as an integer 44 * @param nativeValue native enum value 45 */ AwsEccCurve(int nativeValue)46 AwsEccCurve(int nativeValue) { 47 this.nativeValue = nativeValue; 48 } 49 50 /** 51 * Gets the native enum value as an integer that is associated with this Java enum value 52 * @return this value's associated native enum value 53 */ getNativeValue()54 public int getNativeValue() { return nativeValue; } 55 56 /** 57 * Creates a Java enum value from a native enum value as an integer 58 * @param value native enum value 59 * @return the corresponding Java enum value 60 */ getEnumValueFromInteger(int value)61 public static AwsEccCurve getEnumValueFromInteger(int value) { 62 AwsEccCurve enumValue = enumMapping.get(value); 63 if (enumValue != null) { 64 return enumValue; 65 } 66 67 throw new RuntimeException("Illegal ecc curve name value"); 68 } 69 buildEnumMapping()70 private static Map<Integer, AwsEccCurve> buildEnumMapping() { 71 Map<Integer, AwsEccCurve> enumMapping = new HashMap<Integer, AwsEccCurve>(); 72 enumMapping.put(AWS_ECDSA_P256.getNativeValue(), AWS_ECDSA_P256); 73 enumMapping.put(AWS_ECDSA_P384.getNativeValue(), AWS_ECDSA_P384); 74 75 return enumMapping; 76 } 77 78 private int nativeValue; 79 80 private static Map<Integer, AwsEccCurve> enumMapping = buildEnumMapping(); 81 } 82 83 /** 84 * Creates a new ecc key pair. Only called from native at the moment. 85 * 86 * @param nativeHandle handle to the native ecc key pair object 87 */ EccKeyPair(long nativeHandle)88 private EccKeyPair(long nativeHandle) { 89 acquireNativeHandle(nativeHandle); 90 } 91 92 /** 93 * Determines whether a resource releases its dependencies at the same time the native handle is released or if it waits. 94 * Resources that wait are responsible for calling releaseReferences() manually. 95 */ 96 @Override canReleaseReferencesImmediately()97 protected boolean canReleaseReferencesImmediately() { return true; } 98 99 /** 100 * Releases the instance's reference to the underlying native key pair 101 */ 102 @Override releaseNativeHandle()103 protected void releaseNativeHandle() { 104 if (!isNull()) { 105 eccKeyPairRelease(getNativeHandle()); 106 } 107 } 108 109 /** 110 * Derives the associated ECC key from a pair of AWS credentials according to the sigv4a ecc key 111 * derivation specification. 112 * 113 * @param credentials AWS credentials to derive the associated key for 114 * @param curve ECC curve to use (only P256 is currently supported) 115 * @return derived ecc key pair associated with the AWS credentials 116 */ newDeriveFromCredentials(Credentials credentials, AwsEccCurve curve)117 static public EccKeyPair newDeriveFromCredentials(Credentials credentials, AwsEccCurve curve) { 118 long nativeHandle = eccKeyPairNewFromCredentials(credentials, curve.getNativeValue()); 119 if (nativeHandle != 0) { 120 return new EccKeyPair(nativeHandle); 121 } 122 123 return null; 124 } 125 126 /** 127 * Sign a message using the ECC key pair via ECDSA 128 * @param message message to sign 129 * @return the ECDSA signature of the message 130 */ signMessage(byte[] message)131 public byte[] signMessage(byte[] message) { 132 return eccKeyPairSignMessage(getNativeHandle(), message); 133 } 134 135 /******************************************************************************* 136 * native methods 137 ******************************************************************************/ eccKeyPairNewFromCredentials(Credentials credentials, int curve)138 private static native long eccKeyPairNewFromCredentials(Credentials credentials, int curve); eccKeyPairRelease(long ecc_key_pair)139 private static native void eccKeyPairRelease(long ecc_key_pair); 140 eccKeyPairSignMessage(long ecc_key_pair, byte[] message)141 private static native byte[] eccKeyPairSignMessage(long ecc_key_pair, byte[] message); 142 }; 143