Convert asn1_dsa.c to use the PACKET API instead
[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 #include "internal/packet.h"
28
29 #define ID_SEQUENCE 0x30
30 #define ID_INTEGER 0x02
31
32 /*
33  * Outputs the encoding of the length octets for a DER value with a content
34  * length of cont_len bytes to *ppout and, if successful, increments *ppout
35  * past the data just written.
36  *
37  * The maximum supported content length is 65535 (0xffff) bytes.
38  * The maximum returned length in bytes of the encoded output is 3.
39  *
40  * If ppout is NULL then the output size is calculated and returned but no
41  * output is produced.
42  * If ppout is not NULL then *ppout must not be NULL.
43  *
44  * An attempt to produce more than len bytes results in an error.
45  * Returns the number of bytes of output produced (or that would be produced)
46  * or 0 if an error occurs.
47  */
48 size_t encode_der_length(size_t cont_len, unsigned char **ppout, size_t len)
49 {
50     size_t encoded_len;
51
52     if (cont_len <= 0x7f) {
53         encoded_len = 1;
54     } else if (cont_len <= 0xff) {
55         encoded_len = 2;
56     } else if (cont_len <= 0xffff) {
57         encoded_len = 3;
58     } else {
59         /* Too large for supported length encodings */
60         return 0;
61     }
62     if (encoded_len > len)
63         return 0;
64     if (ppout != NULL) {
65         unsigned char *out = *ppout;
66         switch (encoded_len) {
67         case 2:
68             *out++ = 0x81;
69             break;
70         case 3:
71             *out++ = 0x82;
72             *out++ = (unsigned char)(cont_len >> 8);
73             break;
74         }
75         *out++ = (unsigned char)cont_len;
76         *ppout = out;
77     }
78     return encoded_len;
79 }
80
81 /*
82  * Outputs the DER encoding of a positive ASN.1 INTEGER to *ppout and, if
83  * successful, increments *ppout past the data just written.
84  *
85  * If n is negative then an error results.
86  * If ppout is NULL then the output size is calculated and returned but no
87  * output is produced.
88  * If ppout is not NULL then *ppout must not be NULL.
89  *
90  * An attempt to produce more than len bytes results in an error.
91  * Returns the number of bytes of output produced (or that would be produced)
92  * or 0 if an error occurs.
93  */
94 size_t encode_der_integer(const BIGNUM *n, unsigned char **ppout, size_t len)
95 {
96     unsigned char *out = NULL;
97     unsigned char **pp = NULL;
98     size_t produced;
99     size_t c;
100     size_t cont_len;
101
102     if (len < 1 || BN_is_negative(n))
103         return 0;
104
105     /*
106      * Calculate the ASN.1 INTEGER DER content length for n.
107      * This is the number of whole bytes required to represent n (i.e. rounded
108      * down), plus one.
109      * If n is zero then the content is a single zero byte (length = 1).
110      * If the number of bits of n is a multiple of 8 then an extra zero padding
111      * byte is included to ensure that the value is still treated as positive
112      * in the INTEGER two's complement representation.
113      */
114     cont_len = BN_num_bits(n) / 8 + 1;
115
116     if (ppout != NULL) {
117         out = *ppout;
118         pp = &out;
119         *out++ = ID_INTEGER;
120     }
121     produced = 1;
122     if ((c = encode_der_length(cont_len, pp, len - produced)) == 0)
123         return 0;
124     produced += c;
125     if (cont_len > len - produced)
126         return 0;
127     if (pp != NULL) {
128         if (BN_bn2binpad(n, out, (int)cont_len) != (int)cont_len)
129             return 0;
130         out += cont_len;
131         *ppout = out;
132     }
133     produced += cont_len;
134     return produced;
135 }
136
137 /*
138  * Outputs the DER encoding of a DSA-Sig-Value or ECDSA-Sig-Value to *ppout
139  * and increments *ppout past the data just written.
140  *
141  * If ppout is NULL then the output size is calculated and returned but no
142  * output is produced.
143  * If ppout is not NULL then *ppout must not be NULL.
144  *
145  * An attempt to produce more than len bytes results in an error.
146  * Returns the number of bytes of output produced (or that would be produced)
147  * or 0 if an error occurs.
148  */
149 size_t encode_der_dsa_sig(const BIGNUM *r, const BIGNUM *s,
150                           unsigned char **ppout, size_t len)
151 {
152     unsigned char *out = NULL;
153     unsigned char **pp = NULL;
154     size_t produced;
155     size_t c;
156     size_t r_der_len;
157     size_t s_der_len;
158     size_t cont_len;
159
160     if (len < 1
161             || (r_der_len = encode_der_integer(r, NULL, SIZE_MAX)) == 0
162             || (s_der_len = encode_der_integer(s, NULL, SIZE_MAX)) == 0)
163         return 0;
164
165     cont_len = r_der_len + s_der_len;
166
167     if (ppout != NULL) {
168         out = *ppout;
169         pp = &out;
170         *out++ = ID_SEQUENCE;
171     }
172     produced = 1;
173     if ((c = encode_der_length(cont_len, pp, len - produced)) == 0)
174         return 0;
175     produced += c;
176     if ((c = encode_der_integer(r, pp, len - produced)) == 0)
177         return 0;
178     produced += c;
179     if ((c = encode_der_integer(s, pp, len - produced)) == 0)
180         return 0;
181     produced += c;
182     if (pp != NULL)
183         *ppout = out;
184     return produced;
185 }
186
187 /*
188  * Decodes the DER length octets in pkt and initialises subpkt with the
189  * following bytes of that length.
190  * 
191  * Returns 1 on success or 0 on failure.
192  */
193 int decode_der_length(PACKET *pkt, PACKET *subpkt)
194 {
195     unsigned int byte;
196
197     if (!PACKET_get_1(pkt, &byte))
198         return 0;
199
200     if (byte < 0x80)
201         return PACKET_get_sub_packet(pkt, subpkt, (size_t)byte);
202     if (byte == 0x81)
203         return PACKET_get_length_prefixed_1(pkt, subpkt);
204     if (byte == 0x82)
205         return PACKET_get_length_prefixed_2(pkt, subpkt);
206
207     /* Too large, invalid, or not DER. */
208     return 0;
209 }
210
211 /*
212  * Decodes a single ASN.1 INTEGER value from pkt, which must be DER encoded,
213  * and updates n with the decoded value.
214  *
215  * The BIGNUM, n, must have already been allocated by calling BN_new().
216  * pkt must not be NULL.
217  *
218  * An attempt to consume more than len bytes results in an error.
219  * Returns 1 on success or 0 on error.
220  *
221  * If the PACKET is supposed to only contain a single INTEGER value with no
222  * trailing garbage then it is up to the caller to verify that all bytes
223  * were consumed.
224  */
225 int decode_der_integer(PACKET *pkt, BIGNUM *n)
226 {
227     PACKET contpkt, tmppkt;
228     unsigned int tag, tmp;
229
230     /* Check we have an integer and get the content bytes */
231     if (!PACKET_get_1(pkt, &tag)
232             || tag != ID_INTEGER
233             || !decode_der_length(pkt, &contpkt))
234         return 0;
235
236     /* Peek ahead at the first bytes to check for proper encoding */
237     tmppkt = contpkt;
238     /* The INTEGER must be positive */
239     if (!PACKET_get_1(&tmppkt, &tmp)
240             || (tmp & 0x80) != 0)
241         return 0;
242     /* If there a zero padding byte the next byte must have the msb set */
243     if (PACKET_remaining(&tmppkt) > 0 && tmp == 0) {
244         if (!PACKET_get_1(&tmppkt, &tmp)
245                 || (tmp & 0x80) == 0)
246             return 0;
247     }
248
249     if (BN_bin2bn(PACKET_data(&contpkt),
250                   (int)PACKET_remaining(&contpkt), n) == NULL)
251         return 0;
252
253     return 1;
254 }
255
256 /*
257  * Decodes a single DSA-Sig-Value or ECDSA-Sig-Value from *ppin, which must be
258  * DER encoded, updates r and s with the decoded values, and increments *ppin
259  * past the data that was consumed.
260  *
261  * The BIGNUMs, r and s, must have already been allocated by calls to BN_new().
262  * ppin and *ppin must not be NULL.
263  *
264  * An attempt to consume more than len bytes results in an error.
265  * Returns the number of bytes of input consumed or 0 if an error occurs.
266  *
267  * If the buffer is supposed to only contain a single [EC]DSA-Sig-Value with no
268  * trailing garbage then it is up to the caller to verify that all bytes
269  * were consumed.
270  */
271 size_t decode_der_dsa_sig(BIGNUM *r, BIGNUM *s, const unsigned char **ppin,
272                           size_t len)
273 {
274     size_t consumed;
275     PACKET pkt, contpkt;
276     unsigned int tag;
277
278     if (!PACKET_buf_init(&pkt, *ppin, len)
279             || !PACKET_get_1(&pkt, &tag)
280             || tag != ID_SEQUENCE
281             || !decode_der_length(&pkt, &contpkt)
282             || !decode_der_integer(&contpkt, r)
283             || !decode_der_integer(&contpkt, s)
284             || PACKET_remaining(&contpkt) != 0)
285         return 0;
286
287     consumed = PACKET_data(&pkt) - *ppin;
288     *ppin += consumed;
289     return consumed;
290 }
291