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, <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 * 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