1/*
2 * Copyright (C) 2017 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 */
16
17package org.conscrypt;
18
19import java.io.IOException;
20import java.security.AlgorithmParametersSpi;
21import java.security.spec.AlgorithmParameterSpec;
22import java.security.spec.InvalidParameterSpecException;
23import javax.crypto.spec.IvParameterSpec;
24
25/**
26 * An implementation of {@link java.security.AlgorithmParameters} that contains only an IV.  The
27 * supported encoding formats are ASN.1 (primary) and RAW.
28 *
29 * @hide
30 */
31@Internal
32public class IvParameters extends AlgorithmParametersSpi {
33    private byte[] iv;
34
35    @Override
36    protected void engineInit(AlgorithmParameterSpec algorithmParameterSpec)
37            throws InvalidParameterSpecException {
38        if (!(algorithmParameterSpec instanceof IvParameterSpec)) {
39            throw new InvalidParameterSpecException("Only IvParameterSpec is supported");
40        }
41        iv = ((IvParameterSpec) algorithmParameterSpec).getIV().clone();
42    }
43
44    @Override
45    protected void engineInit(byte[] bytes) throws IOException {
46        long readRef = 0;
47        try {
48            readRef = NativeCrypto.asn1_read_init(bytes);
49            byte[] newIv = NativeCrypto.asn1_read_octetstring(readRef);
50            if (!NativeCrypto.asn1_read_is_empty(readRef)) {
51                throw new IOException("Error reading ASN.1 encoding");
52            }
53            this.iv = newIv;
54        } finally {
55            NativeCrypto.asn1_read_free(readRef);
56        }
57    }
58
59    @Override
60    protected void engineInit(byte[] bytes, String format) throws IOException {
61        if (format == null || format.equals("ASN.1")) {
62            engineInit(bytes);
63        } else if (format.equals("RAW")) {
64            iv = bytes.clone();
65        } else {
66            throw new IOException("Unsupported format: " + format);
67        }
68    }
69
70    @Override
71    @SuppressWarnings("unchecked")
72    protected <T extends AlgorithmParameterSpec> T engineGetParameterSpec(Class<T> aClass)
73            throws InvalidParameterSpecException {
74        if (aClass != IvParameterSpec.class) {
75            throw new InvalidParameterSpecException(
76                    "Incompatible AlgorithmParametersSpec class: " + aClass);
77        }
78        return (T) new IvParameterSpec(iv);
79    }
80
81    @Override
82    protected byte[] engineGetEncoded() throws IOException {
83        long cbbRef = 0;
84        try {
85            cbbRef = NativeCrypto.asn1_write_init();
86            NativeCrypto.asn1_write_octetstring(cbbRef, this.iv);
87            return NativeCrypto.asn1_write_finish(cbbRef);
88        } catch (IOException e) {
89            NativeCrypto.asn1_write_cleanup(cbbRef);
90            throw e;
91        } finally {
92            NativeCrypto.asn1_write_free(cbbRef);
93        }
94    }
95
96    @Override
97    protected byte[] engineGetEncoded(String format) throws IOException {
98        if (format == null || format.equals("ASN.1")) {
99            return engineGetEncoded();
100        } else if (format.equals("RAW")) {
101            return iv.clone();
102        } else {
103            throw new IOException("Unsupported format: " + format);
104        }
105    }
106
107    @Override
108    protected String engineToString() {
109        return "Conscrypt IV AlgorithmParameters";
110    }
111
112    public static class AES extends IvParameters {}
113    public static class DESEDE extends IvParameters {}
114    public static class ChaCha20 extends IvParameters {}
115}
116