1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /**
6  * Licensed to the Apache Software Foundation (ASF) under one
7  * or more contributor license agreements. See the NOTICE file
8  * distributed with this work for additional information
9  * regarding copyright ownership. The ASF licenses this file
10  * to you under the Apache License, Version 2.0 (the
11  * "License"); you may not use this file except in compliance
12  * with the License. You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing,
17  * software distributed under the License is distributed on an
18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19  * KIND, either express or implied. See the License for the
20  * specific language governing permissions and limitations
21  * under the License.
22  */
23 package com.sun.org.apache.xml.internal.security.utils;
24 
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.nio.file.Files;
30 import java.nio.file.Paths;
31 import java.security.SecurityPermission;
32 
33 /**
34  * A collection of different, general-purpose methods for JAVA-specific things
35  */
36 public final class JavaUtils {
37 
38     private static final com.sun.org.slf4j.internal.Logger LOG =
39         com.sun.org.slf4j.internal.LoggerFactory.getLogger(JavaUtils.class);
40 
41     private static final SecurityPermission REGISTER_PERMISSION =
42         new SecurityPermission("com.sun.org.apache.xml.internal.security.register");
43 
JavaUtils()44     private JavaUtils() {
45         // we don't allow instantiation
46     }
47 
48     /**
49      * Method getBytesFromFile
50      *
51      * @param fileName
52      * @return the bytes read from the file
53      *
54      * @throws FileNotFoundException
55      * @throws IOException
56      */
getBytesFromFile(String fileName)57     public static byte[] getBytesFromFile(String fileName)
58         throws FileNotFoundException, IOException {
59 
60         byte refBytes[] = null;
61 
62         try (InputStream inputStream = Files.newInputStream(Paths.get(fileName));
63             UnsyncByteArrayOutputStream baos = new UnsyncByteArrayOutputStream()) {
64             byte buf[] = new byte[1024];
65             int len;
66 
67             while ((len = inputStream.read(buf)) > 0) {
68                 baos.write(buf, 0, len);
69             }
70 
71             refBytes = baos.toByteArray();
72         }
73 
74         return refBytes;
75     }
76 
77     /**
78      * Method writeBytesToFilename
79      *
80      * @param filename
81      * @param bytes
82      */
writeBytesToFilename(String filename, byte[] bytes)83     public static void writeBytesToFilename(String filename, byte[] bytes) {
84         if (filename != null && bytes != null) {
85             try (OutputStream outputStream = Files.newOutputStream(Paths.get(filename))) {
86                 outputStream.write(bytes);
87             } catch (IOException ex) {
88                 LOG.debug(ex.getMessage(), ex);
89             }
90         } else {
91             LOG.debug("writeBytesToFilename got null byte[] pointed");
92         }
93     }
94 
95     /**
96      * This method reads all bytes from the given InputStream till EOF and
97      * returns them as a byte array.
98      *
99      * @param inputStream
100      * @return the bytes read from the stream
101      *
102      * @throws FileNotFoundException
103      * @throws IOException
104      */
getBytesFromStream(InputStream inputStream)105     public static byte[] getBytesFromStream(InputStream inputStream) throws IOException {
106         try (UnsyncByteArrayOutputStream baos = new UnsyncByteArrayOutputStream()) {
107             byte buf[] = new byte[4 * 1024];
108             int len;
109             while ((len = inputStream.read(buf)) > 0) {
110                 baos.write(buf, 0, len);
111             }
112             return baos.toByteArray();
113         }
114     }
115 
116     /**
117      * Converts an ASN.1 DSA value to a XML Signature DSA Value.
118      *
119      * The JCE DSA Signature algorithm creates ASN.1 encoded (r, s) value
120      * pairs (see section 2.2.2 of RFC 3279); the XML Signature requires the
121      * core BigInteger values.
122      *
123      * @param asn1Bytes the ASN.1 encoded bytes
124      * @param size size of r and s in bytes
125      * @return the XML Signature encoded bytes
126      * @throws IOException if the bytes are not encoded correctly
127      * @see <A HREF="http://www.w3.org/TR/xmldsig-core1/#sec-DSA">6.4.1 DSA</A>
128      */
convertDsaASN1toXMLDSIG(byte[] asn1Bytes, int size)129     public static byte[] convertDsaASN1toXMLDSIG(byte[] asn1Bytes, int size)
130         throws IOException
131     {
132         if (asn1Bytes[0] != 48 || asn1Bytes[1] != asn1Bytes.length - 2
133             || asn1Bytes[2] != 2) {
134             throw new IOException("Invalid ASN.1 format of DSA signature");
135         }
136 
137         byte rLength = asn1Bytes[3];
138         int i;
139         for (i = rLength; i > 0 && asn1Bytes[4 + rLength - i] == 0; i--); //NOPMD
140 
141         byte sLength = asn1Bytes[5 + rLength];
142         int j;
143         for (j = sLength; j > 0 && asn1Bytes[6 + rLength + sLength - j] == 0; j--); //NOPMD
144 
145         if (i > size || asn1Bytes[4 + rLength] != 2 || j > size) {
146             throw new IOException("Invalid ASN.1 format of DSA signature");
147         } else {
148             byte[] xmldsigBytes = new byte[size * 2];
149             System.arraycopy(asn1Bytes, 4 + rLength - i, xmldsigBytes,
150                              size - i, i);
151             System.arraycopy(asn1Bytes, 6 + rLength + sLength - j,
152                              xmldsigBytes, size * 2 - j, j);
153             return xmldsigBytes;
154         }
155     }
156 
157     /**
158      * Converts an XML Signature DSA Value to a ASN.1 DSA value.
159      *
160      * The JCE DSA Signature algorithm creates ASN.1 encoded (r, s) value
161      * pairs (see section 2.2.2 of RFC 3279); the XML Signature requires the
162      * core BigInteger values.
163      *
164      * @param xmldsigBytes the XML Signature encoded bytes
165      * @param size size of r and s in bytes
166      * @return the ASN.1 encoded bytes
167      * @throws IOException if the bytes are not encoded correctly
168      * @see <A HREF="http://www.w3.org/TR/xmldsig-core1/#sec-DSA">6.4.1 DSA</A>
169      */
convertDsaXMLDSIGtoASN1(byte[] xmldsigBytes, int size)170     public static byte[] convertDsaXMLDSIGtoASN1(byte[] xmldsigBytes, int size)
171         throws IOException
172     {
173         int totalSize = size * 2;
174         if (xmldsigBytes.length != totalSize) {
175             throw new IOException("Invalid XMLDSIG format of DSA signature");
176         }
177 
178         int i;
179         for (i = size; i > 0 && xmldsigBytes[size - i] == 0; i--); //NOPMD
180 
181         int j = i;
182         if (xmldsigBytes[size - i] < 0) {
183             j++;
184         }
185 
186         int k;
187         for (k = size; k > 0 && xmldsigBytes[totalSize - k] == 0; k--); //NOPMD
188 
189         int l = k;
190         if (xmldsigBytes[totalSize - k] < 0) {
191             l++;
192         }
193 
194         byte[] asn1Bytes = new byte[6 + j + l];
195         asn1Bytes[0] = 48;
196         asn1Bytes[1] = (byte)(4 + j + l);
197         asn1Bytes[2] = 2;
198         asn1Bytes[3] = (byte)j;
199         System.arraycopy(xmldsigBytes, size - i, asn1Bytes, 4 + j - i, i);
200 
201         asn1Bytes[4 + j] = 2;
202         asn1Bytes[5 + j] = (byte) l;
203         System.arraycopy(xmldsigBytes, totalSize - k, asn1Bytes,
204                          6 + j + l - k, k);
205 
206         return asn1Bytes;
207     }
208 
209     /**
210      * Throws a {@code SecurityException} if a security manager is installed
211      * and the caller is not allowed to register an implementation of an
212      * algorithm, transform, or other security sensitive XML Signature function.
213      *
214      * @throws SecurityException if a security manager is installed and the
215      *    caller has not been granted the
216      *    {@literal "com.sun.org.apache.xml.internal.security.register"}
217      *    {@code SecurityPermission}
218      */
checkRegisterPermission()219     public static void checkRegisterPermission() {
220         SecurityManager sm = System.getSecurityManager();
221         if (sm != null) {
222             sm.checkPermission(REGISTER_PERMISSION);
223         }
224     }
225 }
226