1 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
2 | * project 2000. */ |
3 | /* ==================================================================== |
4 | * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
9 | * |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in |
15 | * the documentation and/or other materials provided with the |
16 | * distribution. |
17 | * |
18 | * 3. All advertising materials mentioning features or use of this |
19 | * software must display the following acknowledgment: |
20 | * "This product includes software developed by the OpenSSL Project |
21 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" |
22 | * |
23 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
24 | * endorse or promote products derived from this software without |
25 | * prior written permission. For written permission, please contact |
26 | * licensing@OpenSSL.org. |
27 | * |
28 | * 5. Products derived from this software may not be called "OpenSSL" |
29 | * nor may "OpenSSL" appear in their names without prior written |
30 | * permission of the OpenSSL Project. |
31 | * |
32 | * 6. Redistributions of any form whatsoever must retain the following |
33 | * acknowledgment: |
34 | * "This product includes software developed by the OpenSSL Project |
35 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" |
36 | * |
37 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
38 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
39 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
40 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
41 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
42 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
43 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
44 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
45 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
46 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
47 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
48 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
49 | * ==================================================================== |
50 | * |
51 | * This product includes cryptographic software written by Eric Young |
52 | * (eay@cryptsoft.com). This product includes software written by Tim |
53 | * Hudson (tjh@cryptsoft.com). */ |
54 | |
55 | #include <openssl/dsa.h> |
56 | |
57 | #include <assert.h> |
58 | |
59 | #include <openssl/bn.h> |
60 | #include <openssl/bytestring.h> |
61 | #include <openssl/err.h> |
62 | #include <openssl/mem.h> |
63 | |
64 | #include "../bytestring/internal.h" |
65 | |
66 | |
67 | static int parse_integer(CBS *cbs, BIGNUM **out) { |
68 | assert(*out == NULL); |
69 | *out = BN_new(); |
70 | if (*out == NULL) { |
71 | return 0; |
72 | } |
73 | return BN_parse_asn1_unsigned(cbs, *out); |
74 | } |
75 | |
76 | static int marshal_integer(CBB *cbb, BIGNUM *bn) { |
77 | if (bn == NULL) { |
78 | // A DSA object may be missing some components. |
79 | OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER); |
80 | return 0; |
81 | } |
82 | return BN_marshal_asn1(cbb, bn); |
83 | } |
84 | |
85 | DSA_SIG *DSA_SIG_parse(CBS *cbs) { |
86 | DSA_SIG *ret = DSA_SIG_new(); |
87 | if (ret == NULL) { |
88 | return NULL; |
89 | } |
90 | CBS child; |
91 | if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || |
92 | !parse_integer(&child, &ret->r) || |
93 | !parse_integer(&child, &ret->s) || |
94 | CBS_len(&child) != 0) { |
95 | OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); |
96 | DSA_SIG_free(ret); |
97 | return NULL; |
98 | } |
99 | return ret; |
100 | } |
101 | |
102 | int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) { |
103 | CBB child; |
104 | if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || |
105 | !marshal_integer(&child, sig->r) || |
106 | !marshal_integer(&child, sig->s) || |
107 | !CBB_flush(cbb)) { |
108 | OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); |
109 | return 0; |
110 | } |
111 | return 1; |
112 | } |
113 | |
114 | DSA *DSA_parse_public_key(CBS *cbs) { |
115 | DSA *ret = DSA_new(); |
116 | if (ret == NULL) { |
117 | return NULL; |
118 | } |
119 | CBS child; |
120 | if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || |
121 | !parse_integer(&child, &ret->pub_key) || |
122 | !parse_integer(&child, &ret->p) || |
123 | !parse_integer(&child, &ret->q) || |
124 | !parse_integer(&child, &ret->g) || |
125 | CBS_len(&child) != 0) { |
126 | OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); |
127 | DSA_free(ret); |
128 | return NULL; |
129 | } |
130 | return ret; |
131 | } |
132 | |
133 | int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) { |
134 | CBB child; |
135 | if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || |
136 | !marshal_integer(&child, dsa->pub_key) || |
137 | !marshal_integer(&child, dsa->p) || |
138 | !marshal_integer(&child, dsa->q) || |
139 | !marshal_integer(&child, dsa->g) || |
140 | !CBB_flush(cbb)) { |
141 | OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); |
142 | return 0; |
143 | } |
144 | return 1; |
145 | } |
146 | |
147 | DSA *DSA_parse_parameters(CBS *cbs) { |
148 | DSA *ret = DSA_new(); |
149 | if (ret == NULL) { |
150 | return NULL; |
151 | } |
152 | CBS child; |
153 | if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || |
154 | !parse_integer(&child, &ret->p) || |
155 | !parse_integer(&child, &ret->q) || |
156 | !parse_integer(&child, &ret->g) || |
157 | CBS_len(&child) != 0) { |
158 | OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); |
159 | DSA_free(ret); |
160 | return NULL; |
161 | } |
162 | return ret; |
163 | } |
164 | |
165 | int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) { |
166 | CBB child; |
167 | if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || |
168 | !marshal_integer(&child, dsa->p) || |
169 | !marshal_integer(&child, dsa->q) || |
170 | !marshal_integer(&child, dsa->g) || |
171 | !CBB_flush(cbb)) { |
172 | OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); |
173 | return 0; |
174 | } |
175 | return 1; |
176 | } |
177 | |
178 | DSA *DSA_parse_private_key(CBS *cbs) { |
179 | DSA *ret = DSA_new(); |
180 | if (ret == NULL) { |
181 | return NULL; |
182 | } |
183 | |
184 | CBS child; |
185 | uint64_t version; |
186 | if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || |
187 | !CBS_get_asn1_uint64(&child, &version)) { |
188 | OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); |
189 | goto err; |
190 | } |
191 | |
192 | if (version != 0) { |
193 | OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION); |
194 | goto err; |
195 | } |
196 | |
197 | if (!parse_integer(&child, &ret->p) || |
198 | !parse_integer(&child, &ret->q) || |
199 | !parse_integer(&child, &ret->g) || |
200 | !parse_integer(&child, &ret->pub_key) || |
201 | !parse_integer(&child, &ret->priv_key) || |
202 | CBS_len(&child) != 0) { |
203 | OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); |
204 | goto err; |
205 | } |
206 | return ret; |
207 | |
208 | err: |
209 | DSA_free(ret); |
210 | return NULL; |
211 | } |
212 | |
213 | int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) { |
214 | CBB child; |
215 | if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || |
216 | !CBB_add_asn1_uint64(&child, 0 /* version */) || |
217 | !marshal_integer(&child, dsa->p) || |
218 | !marshal_integer(&child, dsa->q) || |
219 | !marshal_integer(&child, dsa->g) || |
220 | !marshal_integer(&child, dsa->pub_key) || |
221 | !marshal_integer(&child, dsa->priv_key) || |
222 | !CBB_flush(cbb)) { |
223 | OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); |
224 | return 0; |
225 | } |
226 | return 1; |
227 | } |
228 | |
229 | DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) { |
230 | if (len < 0) { |
231 | return NULL; |
232 | } |
233 | CBS cbs; |
234 | CBS_init(&cbs, *inp, (size_t)len); |
235 | DSA_SIG *ret = DSA_SIG_parse(&cbs); |
236 | if (ret == NULL) { |
237 | return NULL; |
238 | } |
239 | if (out_sig != NULL) { |
240 | DSA_SIG_free(*out_sig); |
241 | *out_sig = ret; |
242 | } |
243 | *inp = CBS_data(&cbs); |
244 | return ret; |
245 | } |
246 | |
247 | int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) { |
248 | CBB cbb; |
249 | if (!CBB_init(&cbb, 0) || |
250 | !DSA_SIG_marshal(&cbb, in)) { |
251 | CBB_cleanup(&cbb); |
252 | return -1; |
253 | } |
254 | return CBB_finish_i2d(&cbb, outp); |
255 | } |
256 | |
257 | DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) { |
258 | if (len < 0) { |
259 | return NULL; |
260 | } |
261 | CBS cbs; |
262 | CBS_init(&cbs, *inp, (size_t)len); |
263 | DSA *ret = DSA_parse_public_key(&cbs); |
264 | if (ret == NULL) { |
265 | return NULL; |
266 | } |
267 | if (out != NULL) { |
268 | DSA_free(*out); |
269 | *out = ret; |
270 | } |
271 | *inp = CBS_data(&cbs); |
272 | return ret; |
273 | } |
274 | |
275 | int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) { |
276 | CBB cbb; |
277 | if (!CBB_init(&cbb, 0) || |
278 | !DSA_marshal_public_key(&cbb, in)) { |
279 | CBB_cleanup(&cbb); |
280 | return -1; |
281 | } |
282 | return CBB_finish_i2d(&cbb, outp); |
283 | } |
284 | |
285 | DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) { |
286 | if (len < 0) { |
287 | return NULL; |
288 | } |
289 | CBS cbs; |
290 | CBS_init(&cbs, *inp, (size_t)len); |
291 | DSA *ret = DSA_parse_private_key(&cbs); |
292 | if (ret == NULL) { |
293 | return NULL; |
294 | } |
295 | if (out != NULL) { |
296 | DSA_free(*out); |
297 | *out = ret; |
298 | } |
299 | *inp = CBS_data(&cbs); |
300 | return ret; |
301 | } |
302 | |
303 | int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) { |
304 | CBB cbb; |
305 | if (!CBB_init(&cbb, 0) || |
306 | !DSA_marshal_private_key(&cbb, in)) { |
307 | CBB_cleanup(&cbb); |
308 | return -1; |
309 | } |
310 | return CBB_finish_i2d(&cbb, outp); |
311 | } |
312 | |
313 | DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) { |
314 | if (len < 0) { |
315 | return NULL; |
316 | } |
317 | CBS cbs; |
318 | CBS_init(&cbs, *inp, (size_t)len); |
319 | DSA *ret = DSA_parse_parameters(&cbs); |
320 | if (ret == NULL) { |
321 | return NULL; |
322 | } |
323 | if (out != NULL) { |
324 | DSA_free(*out); |
325 | *out = ret; |
326 | } |
327 | *inp = CBS_data(&cbs); |
328 | return ret; |
329 | } |
330 | |
331 | int i2d_DSAparams(const DSA *in, uint8_t **outp) { |
332 | CBB cbb; |
333 | if (!CBB_init(&cbb, 0) || |
334 | !DSA_marshal_parameters(&cbb, in)) { |
335 | CBB_cleanup(&cbb); |
336 | return -1; |
337 | } |
338 | return CBB_finish_i2d(&cbb, outp); |
339 | } |
340 | |