]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/asn1_dsa.c
Add simple ASN.1 utils for DSA signature DER.
[thirdparty/openssl.git] / crypto / asn1_dsa.c
1 /*
2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 /*
11 * A simple ASN.1 DER encoder/decoder for DSA-Sig-Value and ECDSA-Sig-Value.
12 *
13 * DSA-Sig-Value ::= SEQUENCE {
14 * r INTEGER,
15 * s INTEGER
16 * }
17 *
18 * ECDSA-Sig-Value ::= SEQUENCE {
19 * r INTEGER,
20 * s INTEGER
21 * }
22 */
23
24 #include <openssl/crypto.h>
25 #include <openssl/bn.h>
26 #include "internal/asn1_dsa.h"
27
28 #define ID_SEQUENCE 0x30
29 #define ID_INTEGER 0x02
30
31 /*
32 * Outputs the encoding of the length octets for a DER value with a content
33 * length of cont_len bytes to *ppout and, if successful, increments *ppout
34 * past the data just written.
35 *
36 * The maximum supported content length is 65535 (0xffff) bytes.
37 * The maximum returned length in bytes of the encoded output is 3.
38 *
39 * If ppout is NULL then the output size is calculated and returned but no
40 * output is produced.
41 * If ppout is not NULL then *ppout must not be NULL.
42 *
43 * An attempt to produce more than len bytes results in an error.
44 * Returns the number of bytes of output produced (or that would be produced)
45 * or 0 if an error occurs.
46 */
47 size_t encode_der_length(size_t cont_len, unsigned char **ppout, size_t len)
48 {
49 size_t encoded_len;
50
51 if (cont_len <= 0x7f) {
52 encoded_len = 1;
53 } else if (cont_len <= 0xff) {
54 encoded_len = 2;
55 } else if (cont_len <= 0xffff) {
56 encoded_len = 3;
57 } else {
58 /* Too large for supported length encodings */
59 return 0;
60 }
61 if (encoded_len > len)
62 return 0;
63 if (ppout != NULL) {
64 unsigned char *out = *ppout;
65 switch (encoded_len) {
66 case 2:
67 *out++ = 0x81;
68 break;
69 case 3:
70 *out++ = 0x82;
71 *out++ = (unsigned char)(cont_len >> 8);
72 break;
73 }
74 *out++ = (unsigned char)cont_len;
75 *ppout = out;
76 }
77 return encoded_len;
78 }
79
80 /*
81 * Outputs the DER encoding of a positive ASN.1 INTEGER to *ppout and, if
82 * successful, increments *ppout past the data just written.
83 *
84 * If n is negative then an error results.
85 * If ppout is NULL then the output size is calculated and returned but no
86 * output is produced.
87 * If ppout is not NULL then *ppout must not be NULL.
88 *
89 * An attempt to produce more than len bytes results in an error.
90 * Returns the number of bytes of output produced (or that would be produced)
91 * or 0 if an error occurs.
92 */
93 size_t encode_der_integer(const BIGNUM *n, unsigned char **ppout, size_t len)
94 {
95 unsigned char *out = NULL;
96 unsigned char **pp = NULL;
97 size_t produced;
98 size_t c;
99 size_t cont_len;
100
101 if (len < 1 || BN_is_negative(n))
102 return 0;
103
104 /*
105 * Calculate the ASN.1 INTEGER DER content length for n.
106 * This is the number of whole bytes required to represent n (i.e. rounded
107 * down), plus one.
108 * If n is zero then the content is a single zero byte (length = 1).
109 * If the number of bits of n is a multiple of 8 then an extra zero padding
110 * byte is included to ensure that the value is still treated as positive
111 * in the INTEGER two's complement representation.
112 */
113 cont_len = BN_num_bits(n) / 8 + 1;
114
115 if (ppout != NULL) {
116 out = *ppout;
117 pp = &out;
118 *out++ = ID_INTEGER;
119 }
120 produced = 1;
121 if ((c = encode_der_length(cont_len, pp, len - produced)) == 0)
122 return 0;
123 produced += c;
124 if (cont_len > len - produced)
125 return 0;
126 if (pp != NULL) {
127 if (BN_bn2binpad(n, out, (int)cont_len) != (int)cont_len)
128 return 0;
129 out += cont_len;
130 *ppout = out;
131 }
132 produced += cont_len;
133 return produced;
134 }
135
136 /*
137 * Outputs the DER encoding of a DSA-Sig-Value or ECDSA-Sig-Value to *ppout
138 * and increments *ppout past the data just written.
139 *
140 * If ppout is NULL then the output size is calculated and returned but no
141 * output is produced.
142 * If ppout is not NULL then *ppout must not be NULL.
143 *
144 * An attempt to produce more than len bytes results in an error.
145 * Returns the number of bytes of output produced (or that would be produced)
146 * or 0 if an error occurs.
147 */
148 size_t encode_der_dsa_sig(const BIGNUM *r, const BIGNUM *s,
149 unsigned char **ppout, size_t len)
150 {
151 unsigned char *out = NULL;
152 unsigned char **pp = NULL;
153 size_t produced;
154 size_t c;
155 size_t r_der_len;
156 size_t s_der_len;
157 size_t cont_len;
158
159 if (len < 1
160 || (r_der_len = encode_der_integer(r, NULL, SIZE_MAX)) == 0
161 || (s_der_len = encode_der_integer(s, NULL, SIZE_MAX)) == 0)
162 return 0;
163
164 cont_len = r_der_len + s_der_len;
165
166 if (ppout != NULL) {
167 out = *ppout;
168 pp = &out;
169 *out++ = ID_SEQUENCE;
170 }
171 produced = 1;
172 if ((c = encode_der_length(cont_len, pp, len - produced)) == 0)
173 return 0;
174 produced += c;
175 if ((c = encode_der_integer(r, pp, len - produced)) == 0)
176 return 0;
177 produced += c;
178 if ((c = encode_der_integer(s, pp, len - produced)) == 0)
179 return 0;
180 produced += c;
181 if (pp != NULL)
182 *ppout = out;
183 return produced;
184 }
185
186 /*
187 * Decodes the DER length octets at *ppin, stores the decoded length to
188 * *pcont_len and, if successful, increments *ppin past the data that was
189 * consumed.
190 *
191 * pcont_len, ppin and *ppin must not be NULL.
192 *
193 * An attempt to consume more than len bytes results in an error.
194 * Returns the number of bytes of input consumed or 0 if an error occurs.
195 */
196 size_t decode_der_length(size_t *pcont_len, const unsigned char **ppin,
197 size_t len)
198 {
199 const unsigned char *in = *ppin;
200 size_t consumed;
201 size_t n;
202
203 if (len < 1)
204 return 0;
205 n = *in++;
206 consumed = 1;
207 if (n > 0x7f) {
208 if (n == 0x81 && len - consumed >= 1) {
209 n = *in++;
210 if (n <= 0x7f)
211 return 0; /* Not DER. */
212 ++consumed;
213 } else if (n == 0x82 && len - consumed >= 2) {
214 n = *in++ << 8;
215 n |= *in++;
216 if (n <= 0xff)
217 return 0; /* Not DER. */
218 consumed += 2;
219 } else {
220 return 0; /* Too large, invalid, or not DER. */
221 }
222 }
223 *pcont_len = n;
224 *ppin = in;
225 return consumed;
226 }
227
228 /*
229 * Decodes a single ASN.1 INTEGER value from *ppin, which must be DER encoded,
230 * updates n with the decoded value, and, if successful, increments *ppin past
231 * the data that was consumed.
232 *
233 * The BIGNUM, n, must have already been allocated by calling BN_new().
234 * ppin and *ppin must not be NULL.
235 *
236 * An attempt to consume more than len bytes results in an error.
237 * Returns the number of bytes of input consumed or 0 if an error occurs.
238 *
239 * If the buffer is supposed to only contain a single INTEGER value with no
240 * trailing garbage then it is up to the caller to verify that all bytes
241 * were consumed.
242 */
243 size_t decode_der_integer(BIGNUM *n, const unsigned char **ppin, size_t len)
244 {
245 const unsigned char *in = *ppin;
246 size_t consumed;
247 size_t c;
248 size_t cont_len;
249
250 if (len < 1 || n == NULL || *in++ != ID_INTEGER)
251 return 0;
252 consumed = 1;
253 if ((c = decode_der_length(&cont_len, &in, len - consumed)) == 0)
254 return 0;
255 consumed += c;
256 /* Check for a positive INTEGER with valid content encoding and decode. */
257 if (cont_len > len - consumed || cont_len < 1 || (in[0] & 0x80) != 0
258 || (cont_len >= 2 && in[0] == 0 && (in[1] & 0x80) == 0)
259 || BN_bin2bn(in, (int)cont_len, n) == NULL)
260 return 0;
261 in += cont_len;
262 consumed += cont_len;
263 *ppin = in;
264 return consumed;
265 }
266
267 static size_t decode_dsa_sig_content(BIGNUM *r, BIGNUM *s,
268 const unsigned char **ppin, size_t len)
269 {
270 const unsigned char *in = *ppin;
271 size_t consumed = 0;
272 size_t c;
273
274 if ((c = decode_der_integer(r, &in, len - consumed)) == 0)
275 return 0;
276 consumed += c;
277 if ((c = decode_der_integer(s, &in, len - consumed)) == 0)
278 return 0;
279 consumed += c;
280 *ppin = in;
281 return consumed;
282 }
283
284 /*
285 * Decodes a single DSA-Sig-Value or ECDSA-Sig-Value from *ppin, which must be
286 * DER encoded, updates r and s with the decoded values, and increments *ppin
287 * past the data that was consumed.
288 *
289 * The BIGNUMs, r and s, must have already been allocated by calls to BN_new().
290 * ppin and *ppin must not be NULL.
291 *
292 * An attempt to consume more than len bytes results in an error.
293 * Returns the number of bytes of input consumed or 0 if an error occurs.
294 *
295 * If the buffer is supposed to only contain a single [EC]DSA-Sig-Value with no
296 * trailing garbage then it is up to the caller to verify that all bytes
297 * were consumed.
298 */
299 size_t decode_der_dsa_sig(BIGNUM *r, BIGNUM *s, const unsigned char **ppin,
300 size_t len)
301 {
302 const unsigned char *in = *ppin;
303 size_t consumed;
304 size_t c;
305 size_t cont_len;
306
307 if (len < 1 || *in++ != ID_SEQUENCE)
308 return 0;
309 consumed = 1;
310 if ((c = decode_der_length(&cont_len, &in, len - consumed)) == 0)
311 return 0;
312 consumed += c;
313 if (cont_len > len - consumed
314 || (c = decode_dsa_sig_content(r, s, &in, cont_len)) == 0
315 || c != cont_len)
316 return 0;
317 consumed += c;
318 *ppin = in;
319 return consumed;
320 }
321