/src/openssl31/crypto/asn1_dsa.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * Copyright 2019-2021 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 "crypto/asn1_dsa.h"  | 
27  |  | #include "internal/packet.h"  | 
28  |  |  | 
29  | 224k  | #define ID_SEQUENCE 0x30  | 
30  | 82.0k  | #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 pkt. The maximum supported content length is  | 
35  |  |  * 65535 (0xffff) bytes.  | 
36  |  |  *  | 
37  |  |  * Returns 1 on success or 0 on error.  | 
38  |  |  */  | 
39  |  | int ossl_encode_der_length(WPACKET *pkt, size_t cont_len)  | 
40  | 1.03M  | { | 
41  | 1.03M  |     if (cont_len > 0xffff)  | 
42  | 48  |         return 0; /* Too large for supported length encodings */  | 
43  |  |  | 
44  | 1.03M  |     if (cont_len > 0xff) { | 
45  | 1.12k  |         if (!WPACKET_put_bytes_u8(pkt, 0x82)  | 
46  | 1.12k  |                 || !WPACKET_put_bytes_u16(pkt, cont_len))  | 
47  | 0  |             return 0;  | 
48  | 1.03M  |     } else { | 
49  | 1.03M  |         if (cont_len > 0x7f  | 
50  | 1.03M  |                 && !WPACKET_put_bytes_u8(pkt, 0x81))  | 
51  | 0  |             return 0;  | 
52  | 1.03M  |         if (!WPACKET_put_bytes_u8(pkt, cont_len))  | 
53  | 0  |             return 0;  | 
54  | 1.03M  |     }  | 
55  |  |  | 
56  | 1.03M  |     return 1;  | 
57  | 1.03M  | }  | 
58  |  |  | 
59  |  | /*  | 
60  |  |  * Outputs the DER encoding of a positive ASN.1 INTEGER to pkt.  | 
61  |  |  *  | 
62  |  |  * Results in an error if n is negative or too large.  | 
63  |  |  *  | 
64  |  |  * Returns 1 on success or 0 on error.  | 
65  |  |  */  | 
66  |  | int ossl_encode_der_integer(WPACKET *pkt, const BIGNUM *n)  | 
67  | 691k  | { | 
68  | 691k  |     unsigned char *bnbytes;  | 
69  | 691k  |     size_t cont_len;  | 
70  |  |  | 
71  | 691k  |     if (BN_is_negative(n))  | 
72  | 0  |         return 0;  | 
73  |  |  | 
74  |  |     /*  | 
75  |  |      * Calculate the ASN.1 INTEGER DER content length for n.  | 
76  |  |      * This is the number of whole bytes required to represent n (i.e. rounded  | 
77  |  |      * down), plus one.  | 
78  |  |      * If n is zero then the content is a single zero byte (length = 1).  | 
79  |  |      * If the number of bits of n is a multiple of 8 then an extra zero padding  | 
80  |  |      * byte is included to ensure that the value is still treated as positive  | 
81  |  |      * in the INTEGER two's complement representation.  | 
82  |  |      */  | 
83  | 691k  |     cont_len = BN_num_bits(n) / 8 + 1;  | 
84  |  |  | 
85  | 691k  |     if (!WPACKET_start_sub_packet(pkt)  | 
86  | 691k  |             || !WPACKET_put_bytes_u8(pkt, ID_INTEGER)  | 
87  | 691k  |             || !ossl_encode_der_length(pkt, cont_len)  | 
88  | 691k  |             || !WPACKET_allocate_bytes(pkt, cont_len, &bnbytes)  | 
89  | 691k  |             || !WPACKET_close(pkt))  | 
90  | 10  |         return 0;  | 
91  |  |  | 
92  | 691k  |     if (bnbytes != NULL  | 
93  | 691k  |             && BN_bn2binpad(n, bnbytes, (int)cont_len) != (int)cont_len)  | 
94  | 0  |         return 0;  | 
95  |  |  | 
96  | 691k  |     return 1;  | 
97  | 691k  | }  | 
98  |  |  | 
99  |  | /*  | 
100  |  |  * Outputs the DER encoding of a DSA-Sig-Value or ECDSA-Sig-Value to pkt. pkt  | 
101  |  |  * may be initialised with a NULL buffer which enables pkt to be used to  | 
102  |  |  * calculate how many bytes would be needed.  | 
103  |  |  *  | 
104  |  |  * Returns 1 on success or 0 on error.  | 
105  |  |  */  | 
106  |  | int ossl_encode_der_dsa_sig(WPACKET *pkt, const BIGNUM *r, const BIGNUM *s)  | 
107  | 340k  | { | 
108  | 340k  |     WPACKET tmppkt, *dummypkt;  | 
109  | 340k  |     size_t cont_len;  | 
110  | 340k  |     int isnull = WPACKET_is_null_buf(pkt);  | 
111  |  |  | 
112  | 340k  |     if (!WPACKET_start_sub_packet(pkt))  | 
113  | 0  |         return 0;  | 
114  |  |  | 
115  | 340k  |     if (!isnull) { | 
116  | 5.08k  |         if (!WPACKET_init_null(&tmppkt, 0))  | 
117  | 0  |             return 0;  | 
118  | 5.08k  |         dummypkt = &tmppkt;  | 
119  | 335k  |     } else { | 
120  |  |         /* If the input packet has a NULL buffer, we don't need a dummy packet */  | 
121  | 335k  |         dummypkt = pkt;  | 
122  | 335k  |     }  | 
123  |  |  | 
124  |  |     /* Calculate the content length */  | 
125  | 340k  |     if (!ossl_encode_der_integer(dummypkt, r)  | 
126  | 340k  |             || !ossl_encode_der_integer(dummypkt, s)  | 
127  | 340k  |             || !WPACKET_get_length(dummypkt, &cont_len)  | 
128  | 340k  |             || (!isnull && !WPACKET_finish(dummypkt))) { | 
129  | 10  |         if (!isnull)  | 
130  | 0  |             WPACKET_cleanup(dummypkt);  | 
131  | 10  |         return 0;  | 
132  | 10  |     }  | 
133  |  |  | 
134  |  |     /* Add the tag and length bytes */  | 
135  | 340k  |     if (!WPACKET_put_bytes_u8(pkt, ID_SEQUENCE)  | 
136  | 340k  |             || !ossl_encode_der_length(pkt, cont_len)  | 
137  |  |                /*  | 
138  |  |                 * Really encode the integers. We already wrote to the main pkt  | 
139  |  |                 * if it had a NULL buffer, so don't do it again  | 
140  |  |                 */  | 
141  | 340k  |             || (!isnull && !ossl_encode_der_integer(pkt, r))  | 
142  | 340k  |             || (!isnull && !ossl_encode_der_integer(pkt, s))  | 
143  | 340k  |             || !WPACKET_close(pkt))  | 
144  | 38  |         return 0;  | 
145  |  |  | 
146  | 340k  |     return 1;  | 
147  | 340k  | }  | 
148  |  |  | 
149  |  | /*  | 
150  |  |  * Decodes the DER length octets in pkt and initialises subpkt with the  | 
151  |  |  * following bytes of that length.  | 
152  |  |  *  | 
153  |  |  * Returns 1 on success or 0 on failure.  | 
154  |  |  */  | 
155  |  | int ossl_decode_der_length(PACKET *pkt, PACKET *subpkt)  | 
156  | 116k  | { | 
157  | 116k  |     unsigned int byte;  | 
158  |  |  | 
159  | 116k  |     if (!PACKET_get_1(pkt, &byte))  | 
160  | 89  |         return 0;  | 
161  |  |  | 
162  | 116k  |     if (byte < 0x80)  | 
163  | 46.6k  |         return PACKET_get_sub_packet(pkt, subpkt, (size_t)byte);  | 
164  | 70.1k  |     if (byte == 0x81)  | 
165  | 1.68k  |         return PACKET_get_length_prefixed_1(pkt, subpkt);  | 
166  | 68.4k  |     if (byte == 0x82)  | 
167  | 5.76k  |         return PACKET_get_length_prefixed_2(pkt, subpkt);  | 
168  |  |  | 
169  |  |     /* Too large, invalid, or not DER. */  | 
170  | 62.6k  |     return 0;  | 
171  | 68.4k  | }  | 
172  |  |  | 
173  |  | /*  | 
174  |  |  * Decodes a single ASN.1 INTEGER value from pkt, which must be DER encoded,  | 
175  |  |  * and updates n with the decoded value.  | 
176  |  |  *  | 
177  |  |  * The BIGNUM, n, must have already been allocated by calling BN_new().  | 
178  |  |  * pkt must not be NULL.  | 
179  |  |  *  | 
180  |  |  * An attempt to consume more than len bytes results in an error.  | 
181  |  |  * Returns 1 on success or 0 on error.  | 
182  |  |  *  | 
183  |  |  * If the PACKET is supposed to only contain a single INTEGER value with no  | 
184  |  |  * trailing garbage then it is up to the caller to verify that all bytes  | 
185  |  |  * were consumed.  | 
186  |  |  */  | 
187  |  | int ossl_decode_der_integer(PACKET *pkt, BIGNUM *n)  | 
188  | 41.9k  | { | 
189  | 41.9k  |     PACKET contpkt, tmppkt;  | 
190  | 41.9k  |     unsigned int tag, tmp;  | 
191  |  |  | 
192  |  |     /* Check we have an integer and get the content bytes */  | 
193  | 41.9k  |     if (!PACKET_get_1(pkt, &tag)  | 
194  | 41.9k  |             || tag != ID_INTEGER  | 
195  | 41.9k  |             || !ossl_decode_der_length(pkt, &contpkt))  | 
196  | 18.2k  |         return 0;  | 
197  |  |  | 
198  |  |     /* Peek ahead at the first bytes to check for proper encoding */  | 
199  | 23.7k  |     tmppkt = contpkt;  | 
200  |  |     /* The INTEGER must be positive */  | 
201  | 23.7k  |     if (!PACKET_get_1(&tmppkt, &tmp)  | 
202  | 23.7k  |             || (tmp & 0x80) != 0)  | 
203  | 5.18k  |         return 0;  | 
204  |  |     /* If there a zero padding byte the next byte must have the msb set */  | 
205  | 18.5k  |     if (PACKET_remaining(&tmppkt) > 0 && tmp == 0) { | 
206  | 2.93k  |         if (!PACKET_get_1(&tmppkt, &tmp)  | 
207  | 2.93k  |                 || (tmp & 0x80) == 0)  | 
208  | 170  |             return 0;  | 
209  | 2.93k  |     }  | 
210  |  |  | 
211  | 18.3k  |     if (BN_bin2bn(PACKET_data(&contpkt),  | 
212  | 18.3k  |                   (int)PACKET_remaining(&contpkt), n) == NULL)  | 
213  | 0  |         return 0;  | 
214  |  |  | 
215  | 18.3k  |     return 1;  | 
216  | 18.3k  | }  | 
217  |  |  | 
218  |  | /*  | 
219  |  |  * Decodes a single DSA-Sig-Value or ECDSA-Sig-Value from *ppin, which must be  | 
220  |  |  * DER encoded, updates r and s with the decoded values, and increments *ppin  | 
221  |  |  * past the data that was consumed.  | 
222  |  |  *  | 
223  |  |  * The BIGNUMs, r and s, must have already been allocated by calls to BN_new().  | 
224  |  |  * ppin and *ppin must not be NULL.  | 
225  |  |  *  | 
226  |  |  * An attempt to consume more than len bytes results in an error.  | 
227  |  |  * Returns the number of bytes of input consumed or 0 if an error occurs.  | 
228  |  |  *  | 
229  |  |  * If the buffer is supposed to only contain a single [EC]DSA-Sig-Value with no  | 
230  |  |  * trailing garbage then it is up to the caller to verify that all bytes  | 
231  |  |  * were consumed.  | 
232  |  |  */  | 
233  |  | size_t ossl_decode_der_dsa_sig(BIGNUM *r, BIGNUM *s,  | 
234  |  |                                const unsigned char **ppin, size_t len)  | 
235  | 112k  | { | 
236  | 112k  |     size_t consumed;  | 
237  | 112k  |     PACKET pkt, contpkt;  | 
238  | 112k  |     unsigned int tag;  | 
239  |  |  | 
240  | 112k  |     if (!PACKET_buf_init(&pkt, *ppin, len)  | 
241  | 112k  |             || !PACKET_get_1(&pkt, &tag)  | 
242  | 112k  |             || tag != ID_SEQUENCE  | 
243  | 112k  |             || !ossl_decode_der_length(&pkt, &contpkt)  | 
244  | 112k  |             || !ossl_decode_der_integer(&contpkt, r)  | 
245  | 112k  |             || !ossl_decode_der_integer(&contpkt, s)  | 
246  | 112k  |             || PACKET_remaining(&contpkt) != 0)  | 
247  | 109k  |         return 0;  | 
248  |  |  | 
249  | 2.59k  |     consumed = PACKET_data(&pkt) - *ppin;  | 
250  | 2.59k  |     *ppin += consumed;  | 
251  | 2.59k  |     return consumed;  | 
252  | 112k  | }  |