1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.common.crypto;
21
22 import java.security.PublicKey;
23 import java.security.cert.X509Certificate;
24 import java.security.interfaces.DSAPublicKey;
25 import java.security.interfaces.ECPublicKey;
26 import java.security.interfaces.RSAPublicKey;
27 import java.util.Set;
28
29 import javax.xml.crypto.dsig.Reference;
30 import javax.xml.crypto.dsig.Transform;
31 import javax.xml.crypto.dsig.XMLSignature;
32
33 import org.apache.wss4j.common.ext.WSSecurityException;
34
35
36
37
38 public class AlgorithmSuiteValidator {
39
40 private static final org.slf4j.Logger LOG =
41 org.slf4j.LoggerFactory.getLogger(AlgorithmSuiteValidator.class);
42
43 private final AlgorithmSuite algorithmSuite;
44
45 public AlgorithmSuiteValidator(
46 AlgorithmSuite algorithmSuite
47 ) {
48 this.algorithmSuite = algorithmSuite;
49 }
50
51
52
53
54 public void checkSignatureMethod(
55 String signatureMethod
56 ) throws WSSecurityException {
57 Set<String> allowedSignatureMethods = algorithmSuite.getSignatureMethods();
58 if (!allowedSignatureMethods.isEmpty()
59 && !allowedSignatureMethods.contains(signatureMethod)) {
60 LOG.warn(
61 "SignatureMethod " + signatureMethod + " does not match required values"
62 );
63 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
64 }
65 }
66
67
68
69
70 public void checkC14nAlgorithm(
71 String c14nAlgorithm
72 ) throws WSSecurityException {
73 Set<String> allowedC14nAlgorithms = algorithmSuite.getC14nAlgorithms();
74 if (!allowedC14nAlgorithms.isEmpty() && !allowedC14nAlgorithms.contains(c14nAlgorithm)) {
75 LOG.warn(
76 "C14nMethod " + c14nAlgorithm + " does not match required value"
77 );
78 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
79 }
80 }
81
82
83
84
85 public void checkSignatureAlgorithms(
86 XMLSignature xmlSignature
87 ) throws WSSecurityException {
88
89 String signatureMethod =
90 xmlSignature.getSignedInfo().getSignatureMethod().getAlgorithm();
91 checkSignatureMethod(signatureMethod);
92
93
94 String c14nMethod =
95 xmlSignature.getSignedInfo().getCanonicalizationMethod().getAlgorithm();
96 checkC14nAlgorithm(c14nMethod);
97
98 for (Object refObject : xmlSignature.getSignedInfo().getReferences()) {
99 Reference reference = (Reference)refObject;
100
101 String digestMethod = reference.getDigestMethod().getAlgorithm();
102 Set<String> allowedDigestAlgorithms = algorithmSuite.getDigestAlgorithms();
103 if (!allowedDigestAlgorithms.isEmpty()
104 && !allowedDigestAlgorithms.contains(digestMethod)) {
105 LOG.warn(
106 "DigestMethod " + digestMethod + " does not match required value"
107 );
108 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
109 }
110
111
112 for (int i = 0; i < reference.getTransforms().size(); i++) {
113 Transform transform = (Transform)reference.getTransforms().get(i);
114 String algorithm = transform.getAlgorithm();
115 Set<String> allowedTransformAlgorithms =
116 algorithmSuite.getTransformAlgorithms();
117 if (!allowedTransformAlgorithms.isEmpty()
118 && !allowedTransformAlgorithms.contains(algorithm)) {
119 LOG.warn(
120 "Transform method " + algorithm + " does not match required value"
121 );
122 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
123 }
124 }
125 }
126 }
127
128 public void checkEncryptionKeyWrapAlgorithm(
129 String keyWrapAlgorithm
130 ) throws WSSecurityException {
131 Set<String> keyWrapAlgorithms = algorithmSuite.getKeyWrapAlgorithms();
132 if (!keyWrapAlgorithms.isEmpty()
133 && !keyWrapAlgorithms.contains(keyWrapAlgorithm)) {
134 LOG.warn(
135 "The Key transport method does not match the requirement"
136 );
137 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
138 }
139 }
140
141 public void checkSymmetricEncryptionAlgorithm(
142 String symmetricAlgorithm
143 ) throws WSSecurityException {
144 Set<String> encryptionMethods = algorithmSuite.getEncryptionMethods();
145 if (!encryptionMethods.isEmpty()
146 && !encryptionMethods.contains(symmetricAlgorithm)) {
147 LOG.warn(
148 "The encryption algorithm does not match the requirement"
149 );
150 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
151 }
152 }
153
154
155
156
157 public void checkAsymmetricKeyLength(
158 X509Certificate[] x509Certificates
159 ) throws WSSecurityException {
160 if (x509Certificates == null) {
161 return;
162 }
163
164 for (X509Certificate cert : x509Certificates) {
165 checkAsymmetricKeyLength(cert.getPublicKey());
166 }
167 }
168
169
170
171
172 public void checkAsymmetricKeyLength(
173 X509Certificate x509Certificate
174 ) throws WSSecurityException {
175 if (x509Certificate == null) {
176 return;
177 }
178
179 checkAsymmetricKeyLength(x509Certificate.getPublicKey());
180 }
181
182
183
184
185 public void checkAsymmetricKeyLength(
186 PublicKey publicKey
187 ) throws WSSecurityException {
188 if (publicKey == null) {
189 return;
190 }
191 if (publicKey instanceof RSAPublicKey) {
192 int modulus = ((RSAPublicKey)publicKey).getModulus().bitLength();
193 if (modulus < algorithmSuite.getMinimumAsymmetricKeyLength()
194 || modulus > algorithmSuite.getMaximumAsymmetricKeyLength()) {
195 LOG.warn(
196 "The asymmetric key length does not match the requirement"
197 );
198 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
199 }
200 } else if (publicKey instanceof DSAPublicKey) {
201 int length = ((DSAPublicKey)publicKey).getParams().getP().bitLength();
202 if (length < algorithmSuite.getMinimumAsymmetricKeyLength()
203 || length > algorithmSuite.getMaximumAsymmetricKeyLength()) {
204 LOG.warn(
205 "The asymmetric key length does not match the requirement"
206 );
207 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
208 }
209 } else if (publicKey instanceof ECPublicKey) {
210 final ECPublicKey ecpriv = (ECPublicKey) publicKey;
211 final java.security.spec.ECParameterSpec spec = ecpriv.getParams();
212 int length = spec.getOrder().bitLength();
213 if (length < algorithmSuite.getMinimumEllipticCurveKeyLength()
214 || length > algorithmSuite.getMaximumEllipticCurveKeyLength()) {
215 LOG.warn("The elliptic curve key length does not match the requirement");
216 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
217 }
218 } else {
219 LOG.warn(
220 "An unknown public key was provided"
221 );
222 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
223 }
224 }
225
226
227
228
229 public void checkSymmetricKeyLength(
230 int secretKeyLength
231 ) throws WSSecurityException {
232 if (secretKeyLength < (algorithmSuite.getMinimumSymmetricKeyLength() / 8)
233 || secretKeyLength > (algorithmSuite.getMaximumSymmetricKeyLength() / 8)) {
234 LOG.warn(
235 "The symmetric key length does not match the requirement"
236 );
237 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
238 }
239 }
240
241
242
243
244 public void checkSignatureDerivedKeyLength(
245 int derivedKeyLength
246 ) throws WSSecurityException {
247 int requiredKeyLength = algorithmSuite.getSignatureDerivedKeyLength();
248 if (requiredKeyLength > 0 && (derivedKeyLength / 8) != requiredKeyLength) {
249 LOG.warn(
250 "The signature derived key length of " + derivedKeyLength + " does not match"
251 + " the requirement of " + requiredKeyLength
252 );
253 }
254 }
255
256
257
258
259 public void checkEncryptionDerivedKeyLength(
260 int derivedKeyLength
261 ) throws WSSecurityException {
262 int requiredKeyLength = algorithmSuite.getEncryptionDerivedKeyLength();
263 if (requiredKeyLength > 0 && (derivedKeyLength / 8) != requiredKeyLength) {
264 LOG.warn(
265 "The encryption derived key length of " + derivedKeyLength + " does not match"
266 + " the requirement of " + requiredKeyLength
267 );
268 }
269 }
270
271
272
273
274 public void checkDerivedKeyAlgorithm(
275 String algorithm
276 ) throws WSSecurityException {
277 Set<String> derivedKeyAlgorithms = algorithmSuite.getDerivedKeyAlgorithms();
278 if (!derivedKeyAlgorithms.isEmpty()
279 && !derivedKeyAlgorithms.contains(algorithm)) {
280 LOG.warn(
281 "The Derived Key Algorithm does not match the requirement"
282 );
283 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
284 }
285 }
286
287 }