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