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 *
octets2hex(unsigned char * ptr,size_t n)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 *
i2octets(int n,size_t i)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
octets2i(unsigned char * ptr,size_t n)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
decode_tag(unsigned char * ptr,int * isnew,int * ltype)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
decode_new_len(unsigned char ** pptr)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
decode_len(unsigned char ** pptr,int ltype)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 *
decode_mpi(unsigned char ** pptr,size_t * sz)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 *
mpi2bn(unsigned char ** pptr,size_t * sz)214 mpi2bn(unsigned char **pptr, size_t *sz)
215 {
216 return (decode_mpi(pptr, sz));
217 }
218 #else
219 BIGNUM *
mpi2bn(unsigned char ** pptr)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
decode_packet(int want,unsigned char ** pptr,size_t nbytes,decoder_t decoder,void * decoder_arg)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, <ype);
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 *
decode_subpacket(unsigned char ** pptr,int * stag,int * sz)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