2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.policy.pdp.test.custom;
23 import java.security.InvalidKeyException;
24 import java.security.NoSuchAlgorithmException;
25 import java.security.PrivateKey;
26 import java.security.PublicKey;
27 import java.util.List;
29 import javax.crypto.BadPaddingException;
30 import javax.crypto.Cipher;
31 import javax.crypto.IllegalBlockSizeException;
32 import javax.crypto.NoSuchPaddingException;
34 import com.att.research.xacml.api.DataType;
35 import com.att.research.xacml.api.DataTypeException;
36 import com.att.research.xacml.api.Identifier;
37 import com.att.research.xacml.api.XACML3;
38 import com.att.research.xacml.std.IdentifierImpl;
39 import com.att.research.xacml.std.StdStatus;
40 import com.att.research.xacml.std.StdStatusCode;
41 import com.att.research.xacml.std.datatypes.DataTypeHexBinary;
42 import com.att.research.xacml.std.datatypes.DataTypeString;
43 import com.att.research.xacml.std.datatypes.HexBinary;
44 import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
45 import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
46 import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
47 import com.att.research.xacmlatt.pdp.policy.FunctionDefinition;
48 import com.att.research.xacmlatt.pdp.std.functions.ConvertedArgument;
50 public class FunctionDefinitionDecrypt implements FunctionDefinition {
51 public static final Identifier FD_RSA_DECRYPT = new IdentifierImpl("urn:com:att:research:xacml:custom:function:3.0:rsa:decrypt");
52 private static final FunctionDefinitionDecrypt singleInstance = new FunctionDefinitionDecrypt();
54 public static FunctionDefinitionDecrypt newInstance() {
55 return singleInstance;
59 public Identifier getId() {
60 return FD_RSA_DECRYPT;
64 public Identifier getDataTypeId() {
65 return XACML3.ID_DATATYPE_STRING;
69 public boolean returnsBag() {
74 public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) {
75 if (arguments == null || arguments.size() < 2) {
76 return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, expecting 2 arguments."));
79 // What is the first argument?
81 FunctionArgument arg0 = arguments.get(0);
84 // We don't support bags right now
86 return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, not expecting a bag for argument 0."));
88 if (arg0.getValue().getDataTypeId().equals(XACML3.ID_DATATYPE_HEXBINARY) == false) {
92 return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, expected a Hex Binary for argument 0."));
95 // Convert the argument
97 ConvertedArgument<HexBinary> data = new ConvertedArgument<HexBinary>(arg0, DataTypeHexBinary.newInstance(), false);
99 return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, argument 0 failed to convert to Hex Binary."));
102 // Ok - check the 2nd argument
104 FunctionArgument arg1 = arguments.get(1);
107 // We don't support bags right now
109 return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, not expecting a bag for argument 1."));
111 if (arg1.getValue().getDataTypeId().equals(DataTypePrivateKey.DT_PRIVATEKEY) ||
112 arg1.getValue().getDataTypeId().equals(DataTypePublicKey.DT_PUBLICKEY)) {
114 // Ok - let's try to decrypt
118 cipher = Cipher.getInstance("RSA");
119 if (arg1.getValue().getDataTypeId().equals(DataTypePrivateKey.DT_PRIVATEKEY)) {
121 // Using the private key
123 DataType<PrivateKey> pkDatatype = DataTypePrivateKey.newInstance();
124 ConvertedArgument<PrivateKey> privateKey = new ConvertedArgument<PrivateKey>(arg1, pkDatatype, false);
125 if ( ! privateKey.isOk()) {
126 return ExpressionResult.newError(new StdStatus(privateKey.getStatus().getStatusCode(), "Decrypt: " + privateKey.getStatus().getStatusMessage()));
131 cipher.init(Cipher.DECRYPT_MODE, privateKey.getValue());
132 } else if (arg1.getValue().getDataTypeId().equals(DataTypePublicKey.DT_PUBLICKEY)) {
134 // Using the private key
136 DataType<PublicKey> pkDatatype = DataTypePublicKey.newInstance();
137 ConvertedArgument<PublicKey> publicKey = new ConvertedArgument<PublicKey>(arg1, pkDatatype, false);
138 if ( ! publicKey.isOk()) {
139 return ExpressionResult.newError(new StdStatus(publicKey.getStatus().getStatusCode(), "Decrypt: " + publicKey.getStatus().getStatusMessage()));
144 cipher.init(Cipher.DECRYPT_MODE, publicKey.getValue());
149 byte[] decryptedData = cipher.doFinal(data.getValue().getData());
150 String decryptedString = new String(decryptedData);
152 // All good, return the decrypted string
154 return ExpressionResult.newSingle(DataTypeString.newInstance().createAttributeValue(decryptedString));
155 } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | DataTypeException e) {
156 return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed: " + e.getLocalizedMessage()));
159 return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, expecting public/private key datatype for argument 1."));