]>
Commit | Line | Data |
---|---|---|
54846b7c DM |
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 |