Changeset View
Changeset View
Standalone View
Standalone View
lib/libve/openpgp/decode.c
- This file was added.
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/*- | |||||
* Copyright (c) 2018, Juniper Networks, Inc. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <libve.h> | |||||
#include "decode.h" | |||||
char * | |||||
octets2hex(unsigned char *ptr, int n) | |||||
{ | |||||
char *hex; | |||||
char *cp; | |||||
int i; | |||||
hex = malloc((size_t)(2*n + 1)); | |||||
if (hex) { | |||||
for (i = 0, cp = hex; i < n; i++) { | |||||
snprintf(&cp[i*2], 3, "%02X", ptr[i]); | |||||
} | |||||
} | |||||
return (hex); | |||||
} | |||||
unsigned char * | |||||
i2octets(int n, int i) | |||||
{ | |||||
static unsigned char o[16]; | |||||
int x, j; | |||||
if (n > 15) | |||||
return (NULL); | |||||
for (j = 0, x = n - 1; x >= 0; x--, j++) { | |||||
o[j] = (unsigned char)((i & (0xff << x * 8)) >> x * 8); | |||||
} | |||||
return (o); | |||||
} | |||||
int | |||||
octets2i(unsigned char *ptr, int n) | |||||
{ | |||||
int i; | |||||
int val; | |||||
for (val = i = 0; i < n; i++) { | |||||
val |= (*ptr++ << ((n - i - 1) * 8)); | |||||
} | |||||
return (val); | |||||
} | |||||
/** | |||||
* @brief decode packet tag | |||||
* | |||||
* Also indicate if new/old and in the later case | |||||
* the length type | |||||
* | |||||
* @sa rfc4880:4.2 | |||||
*/ | |||||
int | |||||
decode_tag(unsigned char *ptr, int *isnew, int *ltype) | |||||
{ | |||||
int tag; | |||||
if (!ptr || !isnew || !ltype) | |||||
return (-1); | |||||
tag = *ptr; | |||||
if (!(tag & 0200)) | |||||
return (-1); /* we are lost! */ | |||||
*isnew = tag & 0100; | |||||
if (*isnew) { | |||||
*ltype = -1; /* irrelevant */ | |||||
tag &= 077; | |||||
} else { | |||||
*ltype = tag & 03; | |||||
tag = (tag & 074) >> 2; | |||||
} | |||||
return (tag); | |||||
} | |||||
/** | |||||
* @brief return packet length | |||||
* | |||||
* @sa rfc4880:4.2.2 | |||||
*/ | |||||
static int | |||||
decode_new_len(unsigned char **pptr) | |||||
{ | |||||
unsigned char *ptr; | |||||
int len = -1; | |||||
if (pptr == NULL) | |||||
return (-1); | |||||
ptr = *pptr; | |||||
if (!(*ptr < 224 || *ptr == 255)) | |||||
return (-1); /* not supported */ | |||||
if (*ptr < 192) | |||||
len = *ptr++; | |||||
else if (*ptr < 224) { | |||||
len = ((*ptr - 192) << 8) + *(ptr+1) + 192; | |||||
ptr++; | |||||
} else if (*ptr == 255) { | |||||
len = (*ptr++ << 24); | |||||
len |= (*ptr++ << 16); | |||||
len |= (*ptr++ < 8); | |||||
len |= *ptr++; | |||||
} | |||||
*pptr = ptr; | |||||
return (len); | |||||
} | |||||
/** | |||||
* @brief return packet length | |||||
* | |||||
* @sa rfc4880:4.2.1 | |||||
*/ | |||||
static int | |||||
decode_len(unsigned char **pptr, int ltype) | |||||
{ | |||||
unsigned char *ptr; | |||||
int len; | |||||
if (ltype < 0) | |||||
return (decode_new_len(pptr)); | |||||
if (pptr == NULL) | |||||
return (-1); | |||||
ptr = *pptr; | |||||
switch (ltype) { | |||||
case 0: | |||||
len = *ptr++; | |||||
break; | |||||
case 1: | |||||
len = (*ptr++ << 8); | |||||
len |= *ptr++; | |||||
break; | |||||
case 2: | |||||
len = *ptr++ << 24; | |||||
len |= *ptr++ << 16; | |||||
len |= *ptr++ << 8; | |||||
len |= *ptr++; | |||||
break; | |||||
case 3: | |||||
default: | |||||
/* Not supported */ | |||||
len = -1; | |||||
} | |||||
*pptr = ptr; | |||||
return (len); | |||||
} | |||||
/** | |||||
* @brief return pointer and length of an mpi | |||||
* | |||||
* @sa rfc4880:3.2 | |||||
*/ | |||||
unsigned char * | |||||
decode_mpi(unsigned char **pptr, size_t *sz) | |||||
{ | |||||
unsigned char *data; | |||||
unsigned char *ptr; | |||||
size_t mlen; | |||||
if (pptr == NULL || sz == NULL) | |||||
return (NULL); | |||||
ptr = *pptr; | |||||
mlen = (size_t)(*ptr++ << 8); | |||||
mlen |= (size_t)*ptr++; /* number of bits */ | |||||
mlen = (mlen + 7) / 8; /* number of bytes */ | |||||
*sz = mlen; | |||||
data = ptr; | |||||
ptr += mlen; | |||||
*pptr = ptr; | |||||
return (data); | |||||
} | |||||
/** | |||||
* @brief return an OpenSSL BIGNUM from mpi | |||||
* | |||||
* @sa rfc4880:3.2 | |||||
*/ | |||||
#ifdef USE_BEARSSL | |||||
unsigned char * | |||||
mpi2bn(unsigned char **pptr, size_t *sz) | |||||
{ | |||||
return (decode_mpi(pptr, sz)); | |||||
} | |||||
#else | |||||
BIGNUM * | |||||
mpi2bn(unsigned char **pptr) | |||||
{ | |||||
BIGNUM *bn = NULL; | |||||
unsigned char *ptr; | |||||
int mlen; | |||||
if (pptr == NULL) | |||||
return (NULL); | |||||
ptr = *pptr; | |||||
mlen = (*ptr++ << 8); | |||||
mlen |= *ptr++; /* number of bits */ | |||||
mlen = (mlen + 7) / 8; /* number of bytes */ | |||||
bn = BN_bin2bn(ptr, mlen, NULL); | |||||
ptr += mlen; | |||||
*pptr = ptr; | |||||
return (bn); | |||||
} | |||||
#endif | |||||
/** | |||||
* @brief decode a packet | |||||
* | |||||
* If want is set, check that the packet tag matches | |||||
* if all good, call the provided decoder with its arg | |||||
* | |||||
* @return count of unconsumed data | |||||
* | |||||
* @sa rfc4880:4.2 | |||||
*/ | |||||
int | |||||
decode_packet(int want, unsigned char **pptr, size_t nbytes, | |||||
decoder_t decoder, void *decoder_arg) | |||||
{ | |||||
int tag; | |||||
unsigned char *ptr; | |||||
unsigned char *nptr; | |||||
int isnew, ltype; | |||||
int len; | |||||
int hlen; | |||||
int rc = 0; | |||||
nptr = ptr = *pptr; | |||||
tag = decode_tag(ptr, &isnew, <ype); | |||||
if (want > 0 && tag != want) | |||||
return (-1); | |||||
ptr++; | |||||
len = rc = decode_len(&ptr, ltype); | |||||
hlen = (int)(ptr - nptr); | |||||
nptr = ptr + len; /* consume it */ | |||||
if (decoder) | |||||
rc = decoder(tag, &ptr, len, decoder_arg); | |||||
*pptr = nptr; | |||||
nbytes -= (size_t)(hlen + len); | |||||
if (rc < 0) | |||||
return (rc); /* error */ | |||||
return ((int)nbytes); /* unconsumed data */ | |||||
} | |||||
/** | |||||
* @brief decode a sub packet | |||||
* | |||||
* @sa rfc4880:5.2.3.1 | |||||
*/ | |||||
unsigned char * | |||||
decode_subpacket(unsigned char **pptr, int *stag, int *sz) | |||||
{ | |||||
unsigned char *ptr; | |||||
int len; | |||||
ptr = *pptr; | |||||
len = decode_len(&ptr, -1); | |||||
*sz = (int)(len + ptr - *pptr); | |||||
*pptr = ptr + len; | |||||
*stag = *ptr++; | |||||
return (ptr); | |||||
} |