1 /*
2  * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.crypto.provider;
27 
28 import java.io.*;
29 import java.math.BigInteger;
30 import java.security.AlgorithmParametersSpi;
31 import java.security.spec.AlgorithmParameterSpec;
32 import java.security.spec.InvalidParameterSpecException;
33 import javax.crypto.spec.PBEParameterSpec;
34 import sun.security.util.HexDumpEncoder;
35 import sun.security.util.*;
36 
37 
38 /**
39  * This class implements the parameter set used with password-based
40  * encryption, which is defined in PKCS#5 as follows:
41  *
42  * <pre>
43  * PBEParameter ::=  SEQUENCE {
44  *     salt   OCTET STRING SIZE(8),
45  *     iterationCount   INTEGER }
46  * </pre>
47  *
48  * @author Jan Luehe
49  *
50  */
51 
52 public final class PBEParameters extends AlgorithmParametersSpi {
53 
54     // the salt
55     private byte[] salt = null;
56 
57     // the iteration count
58     private int iCount = 0;
59 
60     // the cipher parameter
61     private AlgorithmParameterSpec cipherParam = null;
62 
engineInit(AlgorithmParameterSpec paramSpec)63     protected void engineInit(AlgorithmParameterSpec paramSpec)
64         throws InvalidParameterSpecException
65    {
66        if (!(paramSpec instanceof PBEParameterSpec)) {
67            throw new InvalidParameterSpecException
68                ("Inappropriate parameter specification");
69        }
70        this.salt = ((PBEParameterSpec)paramSpec).getSalt().clone();
71        this.iCount = ((PBEParameterSpec)paramSpec).getIterationCount();
72        this.cipherParam = ((PBEParameterSpec)paramSpec).getParameterSpec();
73     }
74 
engineInit(byte[] encoded)75     protected void engineInit(byte[] encoded)
76         throws IOException
77     {
78         try {
79             DerValue val = new DerValue(encoded);
80             if (val.tag != DerValue.tag_Sequence) {
81                 throw new IOException("PBE parameter parsing error: "
82                                       + "not a sequence");
83             }
84             val.data.reset();
85 
86             this.salt = val.data.getOctetString();
87             this.iCount = val.data.getInteger();
88 
89             if (val.data.available() != 0) {
90                 throw new IOException
91                     ("PBE parameter parsing error: extra data");
92             }
93         } catch (NumberFormatException e) {
94             throw new IOException("iteration count too big");
95         }
96     }
97 
engineInit(byte[] encoded, String decodingMethod)98     protected void engineInit(byte[] encoded, String decodingMethod)
99         throws IOException
100     {
101         engineInit(encoded);
102     }
103 
104     protected <T extends AlgorithmParameterSpec>
engineGetParameterSpec(Class<T> paramSpec)105             T engineGetParameterSpec(Class<T> paramSpec)
106         throws InvalidParameterSpecException
107     {
108         if (PBEParameterSpec.class.isAssignableFrom(paramSpec)) {
109             return paramSpec.cast(
110                 new PBEParameterSpec(this.salt, this.iCount, this.cipherParam));
111         } else {
112             throw new InvalidParameterSpecException
113                 ("Inappropriate parameter specification");
114         }
115     }
116 
engineGetEncoded()117     protected byte[] engineGetEncoded() throws IOException {
118         DerOutputStream out = new DerOutputStream();
119         DerOutputStream bytes = new DerOutputStream();
120 
121         bytes.putOctetString(this.salt);
122         bytes.putInteger(this.iCount);
123 
124         out.write(DerValue.tag_Sequence, bytes);
125         return out.toByteArray();
126     }
127 
engineGetEncoded(String encodingMethod)128     protected byte[] engineGetEncoded(String encodingMethod)
129         throws IOException
130     {
131         return engineGetEncoded();
132     }
133 
134     /*
135      * Returns a formatted string describing the parameters.
136      */
engineToString()137     protected String engineToString() {
138         String LINE_SEP = System.lineSeparator();
139         String saltString = LINE_SEP + "    salt:" + LINE_SEP + "[";
140         HexDumpEncoder encoder = new HexDumpEncoder();
141         saltString += encoder.encodeBuffer(salt);
142         saltString += "]";
143 
144         return saltString + LINE_SEP + "    iterationCount:"
145             + LINE_SEP + Debug.toHexString(BigInteger.valueOf(iCount))
146             + LINE_SEP;
147     }
148 }
149