1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package javax.crypto;
19
20import java.nio.ByteBuffer;
21import java.security.InvalidAlgorithmParameterException;
22import java.security.InvalidKeyException;
23import java.security.Key;
24import java.security.spec.AlgorithmParameterSpec;
25
26/**
27 * The <i>Service-Provider Interface</i> (<b>SPI</b>) definition for the {@code
28 * Mac} class.
29 *
30 * @see Mac
31 */
32public abstract class MacSpi {
33
34    /**
35     * Creates a new {@code MacSpi} instance.
36     */
37    public MacSpi() {
38    }
39
40    /**
41     * Returns the length of this MAC (in bytes).
42     *
43     * @return the length of this MAC (in bytes).
44     */
45    protected abstract int engineGetMacLength();
46
47    /**
48     * Initializes this {@code MacSpi} instance with the specified key and
49     * algorithm parameters.
50     *
51     * @param key
52     *            the key to initialize this algorithm.
53     * @param params
54     *            the parameters for this algorithm.
55     * @throws InvalidKeyException
56     *             if the specified key cannot be used to initialize this
57     *             algorithm, or it is {@code null}.
58     * @throws InvalidAlgorithmParameterException
59     *             if the specified parameters cannot be used to initialize this
60     *             algorithm.
61     */
62    protected abstract void engineInit(Key key, AlgorithmParameterSpec params)
63            throws InvalidKeyException, InvalidAlgorithmParameterException;
64
65    /**
66     * Updates this {@code MacSpi} instance with the specified byte.
67     *
68     * @param input
69     *            the byte.
70     */
71    protected abstract void engineUpdate(byte input);
72
73    /**
74     * Updates this {@code MacSpi} instance with the data from the specified
75     * buffer {@code input} from the specified {@code offset} and length {@code
76     * len}.
77     *
78     * @param input
79     *            the buffer.
80     * @param offset
81     *            the offset in the buffer.
82     * @param len
83     *            the length of the data in the buffer.
84     */
85    protected abstract void engineUpdate(byte[] input, int offset, int len);
86
87    /**
88     * Updates this {@code MacSpi} instance with the data from the specified
89     * buffer, starting at {@link ByteBuffer#position()}, including the next
90     * {@link ByteBuffer#remaining()} bytes.
91     *
92     * @param input
93     *            the buffer.
94     */
95    protected void engineUpdate(ByteBuffer input) {
96        if (!input.hasRemaining()) {
97            return;
98        }
99        byte[] bInput;
100        if (input.hasArray()) {
101            bInput = input.array();
102            int offset = input.arrayOffset();
103            int position = input.position();
104            int limit = input.limit();
105            engineUpdate(bInput, offset + position, limit - position);
106            input.position(limit);
107        } else {
108            bInput = new byte[input.limit() - input.position()];
109            input.get(bInput);
110            engineUpdate(bInput, 0, bInput.length);
111        }
112    }
113
114    /**
115     * Computes the digest of this MAC based on the data previously specified in
116     * {@link #engineUpdate} calls.
117     * <p>
118     * This {@code MacSpi} instance is reverted to its initial state and
119     * can be used to start the next MAC computation with the same parameters or
120     * initialized with different parameters.
121     *
122     * @return the generated digest.
123     */
124    protected abstract byte[] engineDoFinal();
125
126    /**
127     * Resets this {@code MacSpi} instance to its initial state.
128     * <p>
129     * This {@code MacSpi} instance is reverted to its initial state and can be
130     * used to start the next MAC computation with the same parameters or
131     * initialized with different parameters.
132     */
133    protected abstract void engineReset();
134
135    /**
136     * Clones this {@code MacSpi} instance.
137     *
138     * @return the cloned instance.
139     * @throws CloneNotSupportedException
140     *             if cloning is not supported.
141     */
142    @Override
143    public Object clone() throws CloneNotSupportedException {
144        return super.clone();
145    }
146}
147