1package org.bouncycastle.asn1.cms;
2
3import org.bouncycastle.asn1.ASN1EncodableVector;
4import org.bouncycastle.asn1.ASN1Integer;
5import org.bouncycastle.asn1.ASN1Object;
6import org.bouncycastle.asn1.ASN1OctetString;
7import org.bouncycastle.asn1.ASN1Primitive;
8import org.bouncycastle.asn1.ASN1Sequence;
9import org.bouncycastle.asn1.DEROctetString;
10import org.bouncycastle.asn1.DERSequence;
11import org.bouncycastle.util.Arrays;
12
13/**
14 * <a href="http://tools.ietf.org/html/rfc5084">RFC 5084</a>: GCMParameters object.
15 * <p>
16 * <pre>
17 GCMParameters ::= SEQUENCE {
18   aes-nonce        OCTET STRING, -- recommended size is 12 octets
19   aes-ICVlen       AES-GCM-ICVlen DEFAULT 12 }
20 * </pre>
21 */
22public class GCMParameters
23    extends ASN1Object
24{
25    private byte[] nonce;
26    private int icvLen;
27
28    /**
29     * Return an GCMParameters object from the given object.
30     * <p>
31     * Accepted inputs:
32     * <ul>
33     * <li> null &rarr; null
34     * <li> {@link org.bouncycastle.asn1.cms.GCMParameters} object
35     * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(Object) ASN1Sequence} input formats with GCMParameters structure inside
36     * </ul>
37     *
38     * @param obj the object we want converted.
39     * @exception IllegalArgumentException if the object cannot be converted.
40     */
41    public static GCMParameters getInstance(
42        Object  obj)
43    {
44        if (obj instanceof GCMParameters)
45        {
46            return (GCMParameters)obj;
47        }
48        else if (obj != null)
49        {
50            return new GCMParameters(ASN1Sequence.getInstance(obj));
51        }
52
53        return null;
54    }
55
56    private GCMParameters(
57        ASN1Sequence seq)
58    {
59        this.nonce = ASN1OctetString.getInstance(seq.getObjectAt(0)).getOctets();
60
61        if (seq.size() == 2)
62        {
63            this.icvLen = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue().intValue();
64        }
65        else
66        {
67            this.icvLen = 12;
68        }
69    }
70
71    public GCMParameters(
72        byte[] nonce,
73        int    icvLen)
74    {
75        this.nonce = Arrays.clone(nonce);
76        this.icvLen = icvLen;
77    }
78
79    public byte[] getNonce()
80    {
81        return Arrays.clone(nonce);
82    }
83
84    public int getIcvLen()
85    {
86        return icvLen;
87    }
88
89    public ASN1Primitive toASN1Primitive()
90    {
91        ASN1EncodableVector    v = new ASN1EncodableVector();
92
93        v.add(new DEROctetString(nonce));
94
95        if (icvLen != 12)
96        {
97            v.add(new ASN1Integer(icvLen));
98        }
99
100        return new DERSequence(v);
101    }
102}
103