xref: /freebsd/lib/libsecureboot/openpgp/decode.c (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1 /*-
2  * Copyright (c) 2018, Juniper Networks, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 #include <libsecureboot.h>
28 
29 #include "decode.h"
30 
31 char *
32 octets2hex(unsigned char *ptr, size_t n)
33 {
34 	char *hex;
35 	char *cp;
36 	size_t i;
37 
38 	hex = malloc(2 * n + 1);
39 	if (hex != NULL) {
40 		for (i = 0, cp = hex; i < n; i++) {
41 			snprintf(&cp[i*2], 3, "%02X", ptr[i]);
42 		}
43 	}
44 	return (hex);
45 }
46 
47 unsigned char *
48 i2octets(int n, size_t i)
49 {
50 	static unsigned char o[16];
51 	int x, j;
52 
53 	if (n > 15)
54 		return (NULL);
55 	for (j = 0, x = n - 1; x >= 0; x--, j++) {
56 		o[j] = (unsigned char)((i & (0xff << x * 8)) >> x * 8);
57 	}
58 	return (o);
59 }
60 
61 int
62 octets2i(unsigned char *ptr, size_t n)
63 {
64 	size_t i;
65 	int val;
66 
67 	for (val = i = 0; i < n; i++) {
68 		val |= (*ptr++ << ((n - i - 1) * 8));
69 	}
70 	return (val);
71 }
72 
73 /**
74  * @brief decode packet tag
75  *
76  * Also indicate if new/old and in the later case
77  * the length type
78  *
79  * @sa rfc4880:4.2
80  */
81 int
82 decode_tag(unsigned char *ptr, int *isnew, int *ltype)
83 {
84 	int tag;
85 
86 	if (!ptr || !isnew || !ltype)
87 		return (-1);
88 	tag = *ptr;
89 
90 	if (!(tag & OPENPGP_TAG_ISTAG))
91 		return (-1);		/* we are lost! */
92 	*isnew = tag & OPENPGP_TAG_ISNEW;
93 	if (*isnew) {
94 		*ltype = -1;		/* irrelevant */
95 		tag &= OPENPGP_TAG_NEW_MASK;
96 	} else {
97 		*ltype = tag & OPENPGP_TAG_OLD_TYPE;
98 		tag = (tag & OPENPGP_TAG_OLD_MASK) >> 2;
99 	}
100 	return (tag);
101 }
102 
103 /**
104  * @brief return packet length
105  *
106  * @sa rfc4880:4.2.2
107  */
108 static int
109 decode_new_len(unsigned char **pptr)
110 {
111 	unsigned char *ptr;
112 	int len = -1;
113 
114 	if (pptr == NULL)
115 		return (-1);
116 	ptr = *pptr;
117 
118 	if (!(*ptr < 224 || *ptr == 255))
119 		return (-1);		/* not supported */
120 
121 	if (*ptr < 192)
122 		len = *ptr++;
123 	else if (*ptr < 224) {
124 		len = ((*ptr - 192) << 8) + *(ptr+1) + 192;
125 		ptr++;
126 	} else if (*ptr == 255) {
127 		len = (*ptr++ << 24);
128 		len |= (*ptr++ << 16);
129 		len |= (*ptr++ < 8);
130 		len |= *ptr++;
131 	}
132 
133 	*pptr = ptr;
134 	return (len);
135 }
136 
137 /**
138  * @brief return packet length
139  *
140  * @sa rfc4880:4.2.1
141  */
142 static int
143 decode_len(unsigned char **pptr, int ltype)
144 {
145 	unsigned char *ptr;
146 	int len;
147 
148 	if (ltype < 0)
149 		return (decode_new_len(pptr));
150 
151 	if (pptr == NULL)
152 		return (-1);
153 
154 	ptr = *pptr;
155 
156 	switch (ltype) {
157 	case 0:
158 		len = *ptr++;
159 		break;
160 	case 1:
161 		len = (*ptr++ << 8);
162 		len |= *ptr++;
163 		break;
164 	case 2:
165 		len =  *ptr++ << 24;
166 		len |= *ptr++ << 16;
167 		len |= *ptr++ << 8;
168 		len |= *ptr++;
169 		break;
170 	case 3:
171 	default:
172 		/* Not supported */
173 		len = -1;
174 	}
175 
176 	*pptr = ptr;
177 	return (len);
178 }
179 
180 /**
181  * @brief return pointer and length of an mpi
182  *
183  * @sa rfc4880:3.2
184  */
185 unsigned char *
186 decode_mpi(unsigned char **pptr, size_t *sz)
187 {
188 	unsigned char *data;
189 	unsigned char *ptr;
190 	size_t mlen;
191 
192 	if (pptr == NULL || sz == NULL)
193 		return (NULL);
194 
195 	ptr = *pptr;
196 
197 	mlen = (size_t)(*ptr++ << 8);
198 	mlen |= (size_t)*ptr++;		/* number of bits */
199 	mlen = (mlen + 7) / 8;		/* number of bytes */
200 	*sz = mlen;
201 	data = ptr;
202 	ptr += mlen;
203 	*pptr = ptr;
204 	return (data);
205 }
206 
207 /**
208  * @brief return an OpenSSL BIGNUM from mpi
209  *
210  * @sa rfc4880:3.2
211  */
212 #ifdef USE_BEARSSL
213 unsigned char *
214 mpi2bn(unsigned char **pptr, size_t *sz)
215 {
216 	return (decode_mpi(pptr, sz));
217 }
218 #else
219 BIGNUM *
220 mpi2bn(unsigned char **pptr)
221 {
222 	BIGNUM *bn = NULL;
223 	unsigned char *ptr;
224 	int mlen;
225 
226 	if (pptr == NULL)
227 		return (NULL);
228 
229 	ptr = *pptr;
230 
231 	mlen = (*ptr++ << 8);
232 	mlen |= *ptr++;			/* number of bits */
233 	mlen = (mlen + 7) / 8;		/* number of bytes */
234 	bn = BN_bin2bn(ptr, mlen, NULL);
235 	ptr += mlen;
236 	*pptr = ptr;
237 
238 	return (bn);
239 }
240 #endif
241 
242 /**
243  * @brief decode a packet
244  *
245  * If want is set, check that the packet tag matches
246  * if all good, call the provided decoder with its arg
247  *
248  * @return count of unconsumed data
249  *
250  * @sa rfc4880:4.2
251  */
252 int
253 decode_packet(int want, unsigned char **pptr, size_t nbytes,
254     decoder_t decoder, void *decoder_arg)
255 {
256 	int tag;
257 	unsigned char *ptr;
258 	unsigned char *nptr;
259 	int isnew, ltype;
260 	int len;
261 	int hlen;
262 	int rc = 0;
263 
264 	nptr = ptr = *pptr;
265 
266 	tag = decode_tag(ptr, &isnew, &ltype);
267 
268 	if (want > 0 && tag != want)
269 		return (-1);
270 	ptr++;
271 
272 	len = rc = decode_len(&ptr, ltype);
273 	hlen = (int)(ptr - nptr);
274 	nptr = ptr + len;		/* consume it */
275 
276 	if (decoder)
277 		rc = decoder(tag, &ptr, len, decoder_arg);
278 	*pptr = nptr;
279 	nbytes -= (size_t)(hlen + len);
280 	if (rc < 0)
281 		return (rc);		/* error */
282 	return ((int)nbytes);		/* unconsumed data */
283 }
284 
285 /**
286  * @brief decode a sub packet
287  *
288  * @sa rfc4880:5.2.3.1
289  */
290 unsigned char *
291 decode_subpacket(unsigned char **pptr, int *stag, int *sz)
292 {
293 	unsigned char *ptr;
294 	int len;
295 
296 	ptr = *pptr;
297 	len = decode_len(&ptr, -1);
298 	*sz = (int)(len + ptr - *pptr);
299 	*pptr = ptr + len;
300 	*stag = *ptr++;
301 	return (ptr);
302 }
303