Welcome to mirror list, hosted at ThFree Co, Russian Federation.

DVCSRequestInfo.java « dvcs « bouncycastle « org « java « main « src « pkix - gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4d0767d87893e24bf8d4d23d6055532795d60444 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package org.bouncycastle.dvcs;

import java.math.BigInteger;
import java.util.Date;

import org.bouncycastle.asn1.dvcs.DVCSRequestInformation;
import org.bouncycastle.asn1.dvcs.DVCSTime;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.PolicyInformation;
import org.bouncycastle.tsp.TimeStampToken;
import org.bouncycastle.util.Arrays;

/**
 * Information piece of DVCS requests.
 * It is common for all types of DVCS requests.
 */
public class DVCSRequestInfo
{
    private DVCSRequestInformation data;

    /**
     * Constructs DVCRequestInfo from byte array (DER encoded DVCSRequestInformation).
     *
     * @param in
     */
    public DVCSRequestInfo(byte[] in)
    {
        this(DVCSRequestInformation.getInstance(in));
    }

    /**
     * Constructs DVCRequestInfo from DVCSRequestInformation ASN.1 structure.
     *
     * @param data
     */
    public DVCSRequestInfo(DVCSRequestInformation data)
    {
        this.data = data;
    }

    /**
     * Converts to corresponding ASN.1 structure (DVCSRequestInformation).
     *
     * @return
     */
    public DVCSRequestInformation toASN1Structure()
    {
        return data;
    }

    //
    // DVCRequestInfo selector interface
    //

    /**
     * Get DVCS version of request.
     *
     * @return
     */
    public int getVersion()
    {
        return data.getVersion();
    }

    /**
     * Get requested service type.
     *
     * @return one of CPD, VSD, VPKC, CCPD (see constants).
     */
    public int getServiceType()
    {
        return data.getService().getValue().intValue();
    }

    /**
     * Get nonce if it is set.
     * Note: this field can be set (if not present) or extended (if present) by DVCS.
     *
     * @return nonce value, or null if it is not set.
     */
    public BigInteger getNonce()
    {
        return data.getNonce();
    }

    /**
     * Get request generation time if it is set.
     *
     * @return time of request, or null if it is not set.
     * @throws DVCSParsingException if a request time is present but cannot be extracted.
     */
    public Date getRequestTime()
        throws DVCSParsingException
    {
        DVCSTime time = data.getRequestTime();

        if (time == null)
        {
            return null;
        }

        try
        {
            if (time.getGenTime() != null)
            {
                return time.getGenTime().getDate();
            }
            else
            {
                TimeStampToken token = new TimeStampToken(time.getTimeStampToken());

                return token.getTimeStampInfo().getGenTime();
            }
        }
        catch (Exception e)
        {
            throw new DVCSParsingException("unable to extract time: " + e.getMessage(), e);
        }
    }

    /**
     * Get names of requesting entity, if set.
     *
     * @return
     */
    public GeneralNames getRequester()
    {
        return data.getRequester();
    }

    /**
     * Get policy, under which the validation is requested.
     *
     * @return policy identifier or null, if any policy is acceptable.
     */
    public PolicyInformation getRequestPolicy()
    {
        if (data.getRequestPolicy() != null)
        {
            return data.getRequestPolicy();
        }
        return null;
    }

    /**
     * Get names of DVCS servers.
     * Note: this field can be set by DVCS.
     *
     * @return
     */
    public GeneralNames getDVCSNames()
    {
        return data.getDVCS();
    }

    /**
     * Get data locations, where the copy of request Data can be obtained.
     * Note: the exact meaning of field is up to applications.
     * Note: this field can be set by DVCS.
     *
     * @return
     */
    public GeneralNames getDataLocations()
    {
        return data.getDataLocations();
    }

    /**
     * Compares two DVCRequestInfo structures: one from DVCRequest, and one from DVCResponse.
     * This function implements RFC 3029, 9.1 checks of reqInfo.
     *
     * @param requestInfo  - DVCRequestInfo of DVCRequest
     * @param responseInfo - DVCRequestInfo of DVCResponse
     * @return true if server's requestInfo matches client's requestInfo
     */
    public static boolean validate(DVCSRequestInfo requestInfo, DVCSRequestInfo responseInfo)
    {
        // RFC 3029, 9.1
        // The DVCS MAY modify the fields:
        // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure.

        DVCSRequestInformation clientInfo = requestInfo.data;
        DVCSRequestInformation serverInfo = responseInfo.data;

        if (clientInfo.getVersion() != serverInfo.getVersion())
        {
            return false;
        }
        if (!clientEqualsServer(clientInfo.getService(), serverInfo.getService()))
        {
            return false;
        }
        if (!clientEqualsServer(clientInfo.getRequestTime(), serverInfo.getRequestTime()))
        {
            return false;
        }
        if (!clientEqualsServer(clientInfo.getRequestPolicy(), serverInfo.getRequestPolicy()))
        {
            return false;
        }
        if (!clientEqualsServer(clientInfo.getExtensions(), serverInfo.getExtensions()))
        {
            return false;
        }

        // RFC 3029, 9.1. The only modification allowed to a 'nonce'
        // is the inclusion of a new field if it was not present,
        // or to concatenate other data to the end (right) of an existing value.

        if (clientInfo.getNonce() != null)
        {
            if (serverInfo.getNonce() == null)
            {
                return false;
            }
            byte[] clientNonce = clientInfo.getNonce().toByteArray();
            byte[] serverNonce = serverInfo.getNonce().toByteArray();
            if (serverNonce.length < clientNonce.length)
            {
                return false;
            }
            if (!Arrays.areEqual(clientNonce, Arrays.copyOfRange(serverNonce, 0, clientNonce.length)))
            {
                return false;
            }
        }

        return true;
    }

    // null-protected compare of any two objects
    private static boolean clientEqualsServer(Object client, Object server)
    {
        return (client == null && server == null) || (client != null && client.equals(server));
    }
}