forked from UnitedID/YubiHSM-java-api
/
AESECBCmd.java
117 lines (104 loc) · 5.97 KB
/
AESECBCmd.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
* Copyright (c) 2011 United ID. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Stefan Wold <stefan.wold@unitedid.org>
*/
package org.unitedid.yhsm.internal;
import static org.unitedid.yhsm.internal.Defines.*;
import static org.unitedid.yhsm.utility.Utils.*;
/** <code>AESECBCmd</code> implements AES ECB block cipher commands for the YubiHSM. */
public class AESECBCmd {
/** Private constructor */
private AESECBCmd() {}
/**
* AES ECB encrypt a plaintext string using a specific key handle.
*
* @param deviceHandler the device handler
* @param keyHandle the key handle to use when encrypting AES ECB
* @param plaintext the plaintext string
* @return a hash string in hex format
* @throws YubiHSMInputException if an argument does not validate
* @throws YubiHSMErrorException if validation fail for some values returned by the YubiHSM
* @throws YubiHSMCommandFailedException if the YubiHSM fail to execute the command
*/
public static String encrypt(DeviceHandler deviceHandler, int keyHandle, String plaintext) throws YubiHSMInputException, YubiHSMErrorException, YubiHSMCommandFailedException {
byte[] cmdBuffer = concatAllArrays(leIntToBA(keyHandle), validateByteArray("plaintext", plaintext.getBytes(), YSM_BLOCK_SIZE, 0, YSM_BLOCK_SIZE));
byte[] result = CommandHandler.execute(deviceHandler, YSM_AES_ECB_BLOCK_ENCRYPT, cmdBuffer, true);
return parseResult(result, keyHandle, YSM_AES_ECB_BLOCK_ENCRYPT, false);
}
/**
* AES ECB decrypt a cipher text using a specific key handle.
*
* @param deviceHandler the device handler
* @param keyHandle the key handle to use when decrypting AES ECB
* @param cipherText the cipher string
* @return a plaintext string
* @throws YubiHSMInputException if an argument does not validate
* @throws YubiHSMErrorException if validation fail for some values returned by the YubiHSM
* @throws YubiHSMCommandFailedException if the YubiHSM fail to execute the command
*/
public static String decrypt(DeviceHandler deviceHandler, int keyHandle, String cipherText) throws YubiHSMErrorException, YubiHSMInputException, YubiHSMCommandFailedException {
byte[] cmdBuffer = concatAllArrays(leIntToBA(keyHandle), validateByteArray("cipherText", hexToByteArray(cipherText), 0, YSM_BLOCK_SIZE, 0));
byte[] result = CommandHandler.execute(deviceHandler, YSM_AES_ECB_BLOCK_DECRYPT, cmdBuffer, true);
return parseResult(result, keyHandle, YSM_AES_ECB_BLOCK_DECRYPT, true);
}
/**
* AES ECB decrypt a cipher text using a specific key handle, and then compare it with the supplied plaintext.
*
* @param deviceHandler the device handler
* @param keyHandle the key handle to use when comparing AES ECB cipher with plaintext
* @param cipherText the cipher string
* @param plaintext the plaintext string
* @return true if successful, false if not successful
* @throws YubiHSMInputException if an argument does not validate
* @throws YubiHSMErrorException if validation fail for some values returned by the YubiHSM
* @throws YubiHSMCommandFailedException if the YubiHSM fail to execute the command
*/
public static boolean compare(DeviceHandler deviceHandler, int keyHandle, String cipherText, String plaintext) throws YubiHSMInputException, YubiHSMErrorException, YubiHSMCommandFailedException {
byte[] cipherTextBA = validateByteArray("cipherText", hexToByteArray(cipherText), 0, YSM_BLOCK_SIZE, 0);
byte[] plaintextBA = validateByteArray("plaintext", plaintext.getBytes(), YSM_BLOCK_SIZE, 0, YSM_BLOCK_SIZE);
byte[] keyHandleBA = leIntToBA(keyHandle);
byte[] cmdBuffer = concatAllArrays(keyHandleBA, cipherTextBA, plaintextBA);
byte[] result = CommandHandler.execute(deviceHandler, YSM_AES_ECB_BLOCK_DECRYPT_CMP, cmdBuffer, true);
validateCmdResponseBA("keyHandle", rangeOfByteArray(result, 0, 4), keyHandleBA);
if (result[4] == YSM_STATUS_OK) {
return true;
} else if (result[4] == YSM_MISMATCH) {
return false;
} else {
throw new YubiHSMCommandFailedException("Command " + getCommandString(YSM_AES_ECB_BLOCK_DECRYPT_CMP) + " failed: " + getCommandStatus(result[4]));
}
}
/**
* Parse the response from the YubiHSM for a previous command.
*
* @param data the YubiHSM response data
* @param keyHandle the key handle used for the command
* @param command the YubiHSM command executed
* @param decrypt a boolean used to toggle if we decrypt (if true plaintext is returned, otherwise a hex string)
* @return a plaintext string or hex string
* @throws YubiHSMErrorException if validation fail for some values returned by the YubiHSM
* @throws YubiHSMCommandFailedException if the YubiHSM fail to execute the command
*/
private static String parseResult(byte[] data, int keyHandle, byte command, boolean decrypt) throws YubiHSMErrorException, YubiHSMCommandFailedException {
validateCmdResponseBA("keyHandle", rangeOfByteArray(data, 0, 4), leIntToBA(keyHandle));
byte[] result = rangeOfByteArray(data, 4, YSM_BLOCK_SIZE);
if (data[20] == YSM_STATUS_OK) {
return decrypt ? new String(result).trim() : byteArrayToHex(result);
} else {
throw new YubiHSMCommandFailedException("Command " + getCommandString(command) + " failed: " + getCommandStatus(result[4]));
}
}
}