1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package libcore.javax.crypto.spec;
17
18import java.security.AlgorithmParameters;
19import java.security.NoSuchAlgorithmException;
20import java.security.Provider;
21import java.security.Security;
22import java.security.spec.MGF1ParameterSpec;
23import java.util.Arrays;
24import java.util.Base64;
25import javax.crypto.spec.OAEPParameterSpec;
26import javax.crypto.spec.PSource;
27import tests.security.AlgorithmParameterAsymmetricHelper;
28import tests.security.AlgorithmParametersTest;
29
30public class AlgorithmParametersTestOAEP extends AlgorithmParametersTest {
31
32    // The ASN.1 encoding for OAEP params (specified in RFC 4055 section 4.1) specifies
33    // default values for all parameters, so we need to consider encodings with those
34    // values both explicitly specified and unspecified.  When encoding values, it is required
35    // that default values are left empty, but implementations must be able to parse explicitly-
36    // specified defaults as well.
37    //
38    // See README.ASN1 for how to understand and reproduce this data.
39
40    // asn1=SEQUENCE
41    private static final String ENCODED_DATA_ALL_DEFAULTS = "MAA=";
42
43    // asn1=SEQUENCE:oaep
44    // [oaep]
45    // hashFunc=EXP:0,SEQUENCE:sha1
46    // maskGenFunc=EXP:1,SEQUENCE:mgf1
47    // pSourceFunc=EXP:2,SEQUENCE:pSpecified
48    // [mgf1]
49    // oid=OID:1.2.840.113549.1.1.8
50    // params=SEQUENCE:sha1
51    // [pSpecified]
52    // oid=OID:1.2.840.113549.1.1.9
53    // val=OCTETSTRING:
54    // [sha1]
55    // oid=OID:sha1
56    // params=NULL
57    private static final String ENCODED_DATA_EXPLICIT_DEFAULTS =
58            "MDigCzAJBgUrDgMCGgUAoRgwFgYJKoZIhvcNAQEIMAkGBSsOAwIaBQCiDzANBgkqhkiG9w0BAQkEAA==";
59
60    // Base64 version of ASN.1-encoded data with none of the default values.  Specifically:
61    // SHA-256 hashFunc, MGF1-SHA-384 maskGenFunc, and [1, 2, 3, 4] pSourceFunc
62
63    // asn1=SEQUENCE:oaep
64    // [oaep]
65    // hashFunc=EXP:0,SEQUENCE:sha256
66    // maskGenFunc=EXP:1,SEQUENCE:mgf1
67    // pSourceFunc=EXP:2,SEQUENCE:pSpecified
68    // [sha256]
69    // oid=OID:sha256
70    // params=NULL
71    // [mgf1]
72    // oid=OID:1.2.840.113549.1.1.8
73    // params=SEQUENCE:sha384
74    // [sha384]
75    // oid=OID:sha384
76    // params=NULL
77    // [pSpecified]
78    // oid=OID:1.2.840.113549.1.1.9
79    // val=FORMAT:HEX,OCTETSTRING:01020304
80    private static final String ENCODED_DATA_NON_DEFAULTS = "MESgDzANBglghkgBZQMEAgEFAKEc"
81            + "MBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgIFAKITMBEGCSqGSIb3DQEBCQQEAQIDBA==";
82
83    // Base64 version of ASN.1-encoded data with some default and some non-default values.
84    // Specifically, SHA-1 hashFunc (default), MGF1-SHA-512 maskGenFunc (non-default),
85    // empty pSourceFunc (default)
86
87    // asn1=SEQUENCE:oaep
88    // [oaep]
89    // maskGenFunc=EXP:1,SEQUENCE:mgf1
90    // [mgf1]
91    // oid=OID:1.2.840.113549.1.1.8
92    // params=SEQUENCE:sha512
93    // [sha512]
94    // oid=OID:sha512
95    // params=NULL
96    private static final String ENCODED_DATA_MIXED = "MB6hHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIDBQA=";
97
98    public AlgorithmParametersTestOAEP() {
99        super("OAEP", new AlgorithmParameterAsymmetricHelper("RSA"), new OAEPParameterSpec("SHA-1", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT));
100    }
101
102    public void testEncoding() throws Exception {
103        for (Provider p : Security.getProviders()) {
104            AlgorithmParameters params;
105            try {
106                params = AlgorithmParameters.getInstance("OAEP", p);
107            } catch (NoSuchAlgorithmException e) {
108                // This provider doesn't support OAEP, ignore
109                continue;
110            }
111
112            OAEPParameterSpec spec = new OAEPParameterSpec(
113                    "SHA-1", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
114            params.init(spec);
115            assertEquals("Provider: " + p.getName(),
116                    ENCODED_DATA_ALL_DEFAULTS,
117                    Base64.getEncoder().encodeToString(params.getEncoded()));
118
119            params = AlgorithmParameters.getInstance("OAEP", p);
120            spec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA384,
121                    new PSource.PSpecified(new byte[] {1, 2, 3, 4}));
122            params.init(spec);
123            assertEquals("Provider: " + p.getName(),
124                    ENCODED_DATA_NON_DEFAULTS,
125                    Base64.getEncoder().encodeToString(params.getEncoded()));
126
127            params = AlgorithmParameters.getInstance("OAEP", p);
128            spec = new OAEPParameterSpec(
129                    "SHA-1", "MGF1", MGF1ParameterSpec.SHA512, PSource.PSpecified.DEFAULT);
130            params.init(spec);
131            assertEquals("Provider: " + p.getName(),
132                    ENCODED_DATA_MIXED,
133                    Base64.getEncoder().encodeToString(params.getEncoded()));
134
135            params = AlgorithmParameters.getInstance("OAEP", p);
136            params.init(Base64.getDecoder().decode(ENCODED_DATA_ALL_DEFAULTS));
137            OAEPParameterSpec producedSpec = params.getParameterSpec(OAEPParameterSpec.class);
138
139            assertEquals("Provider: " + p.getName(), "SHA-1", producedSpec.getDigestAlgorithm());
140            assertEquals("Provider: " + p.getName(), "MGF1", producedSpec.getMGFAlgorithm());
141            assertEquals("Provider: " + p.getName(),
142                    MGF1ParameterSpec.SHA1.getDigestAlgorithm(),
143                    ((MGF1ParameterSpec) producedSpec.getMGFParameters()).getDigestAlgorithm());
144            assertTrue("Provider: " + p.getName(),
145                    Arrays.equals(PSource.PSpecified.DEFAULT.getValue(),
146                            ((PSource.PSpecified) producedSpec.getPSource()).getValue()));
147
148            params = AlgorithmParameters.getInstance("OAEP", p);
149            params.init(Base64.getDecoder().decode(ENCODED_DATA_EXPLICIT_DEFAULTS));
150            producedSpec = params.getParameterSpec(OAEPParameterSpec.class);
151
152            assertEquals("Provider: " + p.getName(), "SHA-1", producedSpec.getDigestAlgorithm());
153            assertEquals("Provider: " + p.getName(), "MGF1", producedSpec.getMGFAlgorithm());
154            assertEquals("Provider: " + p.getName(),
155                    MGF1ParameterSpec.SHA1.getDigestAlgorithm(),
156                    ((MGF1ParameterSpec) producedSpec.getMGFParameters()).getDigestAlgorithm());
157            assertTrue("Provider: " + p.getName(),
158                    Arrays.equals(PSource.PSpecified.DEFAULT.getValue(),
159                            ((PSource.PSpecified) producedSpec.getPSource()).getValue()));
160
161            params = AlgorithmParameters.getInstance("OAEP", p);
162            params.init(Base64.getDecoder().decode(ENCODED_DATA_NON_DEFAULTS));
163            producedSpec = params.getParameterSpec(OAEPParameterSpec.class);
164
165            assertEquals("Provider: " + p.getName(), "SHA-256", producedSpec.getDigestAlgorithm());
166            assertEquals("Provider: " + p.getName(), "MGF1", producedSpec.getMGFAlgorithm());
167            assertEquals("Provider: " + p.getName(),
168                    MGF1ParameterSpec.SHA384.getDigestAlgorithm(),
169                    ((MGF1ParameterSpec) producedSpec.getMGFParameters()).getDigestAlgorithm());
170            assertTrue("Provider: " + p.getName(),
171                    Arrays.equals(new byte[] {1, 2, 3, 4},
172                            ((PSource.PSpecified) producedSpec.getPSource()).getValue()));
173
174            params = AlgorithmParameters.getInstance("OAEP", p);
175            params.init(Base64.getDecoder().decode(ENCODED_DATA_MIXED));
176            producedSpec = params.getParameterSpec(OAEPParameterSpec.class);
177
178            assertEquals("Provider: " + p.getName(), "SHA-1", producedSpec.getDigestAlgorithm());
179            assertEquals("Provider: " + p.getName(), "MGF1", producedSpec.getMGFAlgorithm());
180            assertEquals("Provider: " + p.getName(),
181                    MGF1ParameterSpec.SHA512.getDigestAlgorithm(),
182                    ((MGF1ParameterSpec) producedSpec.getMGFParameters()).getDigestAlgorithm());
183            assertTrue("Provider: " + p.getName(),
184                    Arrays.equals(PSource.PSpecified.DEFAULT.getValue(),
185                            ((PSource.PSpecified) producedSpec.getPSource()).getValue()));
186        }
187    }
188
189}
190