X-Git-Url: http://the.earth.li/gitweb/?p=onak.git;a=blobdiff_plain;f=decodekey.c;h=f8cc40771c63f85e845216b7b0c0a128e5e8fbda;hp=705b827d43ef7a7e69197a9a4dd9af537e81d542;hb=76f079e5ebdb34acaaa2462a8d915ee06d3c8425;hpb=23f086c85c5d2db35e9ce76cf0bbf72200b4dc42 diff --git a/decodekey.c b/decodekey.c index 705b827..f8cc407 100644 --- a/decodekey.c +++ b/decodekey.c @@ -13,11 +13,10 @@ * more details. * * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * this program. If not, see . */ -#include +#include #include #include #include @@ -28,12 +27,13 @@ #include "keyid.h" #include "keystructs.h" #include "ll.h" -#include "log.h" #include "openpgp.h" /* * parse_subpackets - Parse the subpackets of a Type 4 signature. * @data: The subpacket data. + * @len: The amount of data available to read. + * @parselen: The amount of data that was actually parsed. * @keyid: A pointer to where we should return the keyid. * @creationtime: A pointer to where we should return the creation time. * @@ -42,16 +42,31 @@ * processed. If the value of any piece of data is not desired a NULL * can be passed instead of a pointer to a storage area for that value. */ -int parse_subpackets(unsigned char *data, uint64_t *keyid, time_t *creation) +onak_status_t parse_subpackets(unsigned char *data, size_t len, + size_t *parselen, uint64_t *keyid, time_t *creation) { int offset = 0; int length = 0; int packetlen = 0; + struct openpgp_fingerprint fp; + int i; - log_assert(data != NULL); + assert(data != NULL); + + /* Make sure we actually have the 2 byte length field */ + if (len < 2) { + return ONAK_E_INVALID_PKT; + } length = (data[0] << 8) + data[1] + 2; + /* If the length is off the end of the data available, it's bogus */ + if (len < length) { + return ONAK_E_INVALID_PKT; + } + + *parselen = length; + offset = 2; while (offset < length) { packetlen = data[offset++]; @@ -67,6 +82,10 @@ int parse_subpackets(unsigned char *data, uint64_t *keyid, time_t *creation) packetlen <<= 8; packetlen |= data[offset++]; } + /* Check the supplied length is within the remaining data */ + if (packetlen == 0 || (packetlen + offset) > length) { + return ONAK_E_INVALID_PKT; + } switch (data[offset] & 0x7F) { case OPENPGP_SIGSUB_CREATION: /* @@ -105,19 +124,42 @@ int parse_subpackets(unsigned char *data, uint64_t *keyid, time_t *creation) *keyid += data[offset+packetlen - 1]; } break; + case OPENPGP_SIGSUB_ISSUER_FINGER: + if ((packetlen - 2) <= MAX_FINGERPRINT_LEN && + keyid != NULL) { + fp.length = packetlen - 2; + for (i = 0; i < fp.length; i++) { + fp.fp[i] = data[offset + i + 2]; + } + *keyid = fingerprint2keyid(&fp); + } + break; case OPENPGP_SIGSUB_EXPIRY: case OPENPGP_SIGSUB_EXPORTABLE: case OPENPGP_SIGSUB_TRUSTSIG: case OPENPGP_SIGSUB_REGEX: + case OPENPGP_SIGSUB_REVOCABLE: + case OPENPGP_SIGSUB_CAPABILITIES: case OPENPGP_SIGSUB_KEYEXPIRY: + case OPENPGP_SIGSUB_ARR: case OPENPGP_SIGSUB_PREFSYM: + case OPENPGP_SIGSUB_REVOCATION_KEY: + case OPENPGP_SIGSUB_ISSUER_UID: + case OPENPGP_SIGSUB_URL: + case OPENPGP_SIGSUB_X_ISSUER_FINGER: case OPENPGP_SIGSUB_NOTATION: case OPENPGP_SIGSUB_PREFHASH: case OPENPGP_SIGSUB_PREFCOMPRESS: case OPENPGP_SIGSUB_KEYSERVER: + case OPENPGP_SIGSUB_PREFKEYSERVER: case OPENPGP_SIGSUB_PRIMARYUID: case OPENPGP_SIGSUB_POLICYURI: case OPENPGP_SIGSUB_KEYFLAGS: + case OPENPGP_SIGSUB_SIGNER_UID: + case OPENPGP_SIGSUB_REVOKE_REASON: + case OPENPGP_SIGSUB_FEATURES: + case OPENPGP_SIGSUB_SIGNATURE_TARGET: + case OPENPGP_SIGSUB_EMBEDDED_SIG: /* * Various subpacket types we know about, but don't * currently handle. Some are candidates for being @@ -130,38 +172,13 @@ int parse_subpackets(unsigned char *data, uint64_t *keyid, time_t *creation) * 7 is set in which case we log a major error. */ if (data[offset] & 0x80) { - logthing(LOGTHING_CRITICAL, - "Critical subpacket type not parsed: 0x%X", - data[offset]); + return ONAK_E_UNSUPPORTED_FEATURE; } - } offset += packetlen; } - return length; -} - -/** - * keysigs - Return the sigs on a given OpenPGP signature list. - * @curll: The current linked list. Can be NULL to create a new list. - * @sigs: The signature list we want the sigs on. - * - * Returns a linked list of stats_key elements containing the sigs on the - * supplied OpenPGP packet list. - */ -struct ll *keysigs(struct ll *curll, - struct openpgp_packet_list *sigs) -{ - uint64_t keyid = 0; - - while (sigs != NULL) { - keyid = sig_keyid(sigs->packet); - sigs = sigs->next; - curll = lladd(curll, createandaddtohash(keyid)); - } - - return curll; + return ONAK_E_OK; } /** @@ -174,10 +191,12 @@ struct ll *keysigs(struct ll *curll, * key or pulls the data directly from v2/3. NULL can be passed for any * values which aren't cared about. */ -void sig_info(struct openpgp_packet *packet, uint64_t *keyid, time_t *creation) +onak_status_t sig_info(struct openpgp_packet *packet, uint64_t *keyid, + time_t *creation) { - int length = 0; - + size_t length = 0; + onak_status_t res; + if (packet != NULL) { switch (packet->data[0]) { case 2: @@ -210,20 +229,36 @@ void sig_info(struct openpgp_packet *packet, uint64_t *keyid, time_t *creation) } break; case 4: - length = parse_subpackets(&packet->data[4], - keyid, creation); - parse_subpackets(&packet->data[length + 4], - keyid, creation); + case 5: + if (keyid != NULL) { + *keyid = 0; + } + res = parse_subpackets(&packet->data[4], + packet->length - 4, + &length, keyid, creation); + if (res != ONAK_E_OK) { + return res; + } /* - * Don't bother to look at the unsigned packets. + * Only look at the unhashed subpackets if we want the + * keyid and it wasn't in the signed subpacket + * section. */ + if (keyid != NULL && *keyid == 0) { + res = parse_subpackets(&packet->data[length + 4], + packet->length - (4 + length), + &length, keyid, NULL); + if (res != ONAK_E_OK) { + return res; + } + } break; default: break; } } - return; + return ONAK_E_OK; } /** @@ -329,3 +364,82 @@ struct openpgp_fingerprint *keysubkeys(struct openpgp_publickey *key) return subkeys; } + +enum onak_oid onak_parse_oid(uint8_t *buf, size_t len) +{ + enum onak_oid oid; + + /* Elliptic curve key size is based on OID */ + if (len == 0 || (buf[0] >= len)) { + oid = ONAK_OID_INVALID; + /* Curve25519 / 1.3.6.1.4.1.3029.1.5.1 */ + } else if ((buf[0] == 10) && + (buf[1] == 0x2B) && (buf[2] == 0x06) && + (buf[3] == 0x01) && (buf[4] == 0x04) && + (buf[5] == 0x01) && (buf[6] == 0x97) && + (buf[7] == 0x55) && (buf[8] == 0x01) && + (buf[9] == 0x05) && (buf[10] == 0x01)) { + oid = ONAK_OID_CURVE25519; + /* Ed25519 / 1.3.6.1.4.1.11591.15.1 */ + } else if ((buf[0] == 9) && + (buf[1] == 0x2B) && (buf[2] == 0x06) && + (buf[3] == 0x01) && (buf[4] == 0x04) && + (buf[5] == 0x01) && (buf[6] == 0xDA) && + (buf[7] == 0x47) && (buf[8] == 0x0F) && + (buf[9] == 0x01)) { + oid = ONAK_OID_ED25519; + /* nistp256 / 1.2.840.10045.3.1.7 */ + } else if ((buf[0] == 8) && + (buf[1] == 0x2A) && (buf[2] == 0x86) && + (buf[3] == 0x48) && (buf[4] == 0xCE) && + (buf[5] == 0x3D) && (buf[6] == 0x03) && + (buf[7] == 0x01) && (buf[8] == 0x07)) { + oid = ONAK_OID_NISTP256; + /* nistp384 / 1.3.132.0.34 */ + } else if ((buf[0] == 5) && + (buf[1] == 0x2B) && (buf[2] == 0x81) && + (buf[3] == 0x04) && (buf[4] == 0x00) && + (buf[5] == 0x22)) { + oid = ONAK_OID_NISTP384; + /* nistp521 / 1.3.132.0.35 */ + } else if ((buf[0] == 5) && + (buf[1] == 0x2B) && (buf[2] == 0x81) && + (buf[3] == 0x04) && (buf[4] == 0x00) && + (buf[5] == 0x23)) { + oid = ONAK_OID_NISTP521; + /* brainpoolP256r1 / 1.3.36.3.3.2.8.1.1.7 */ + } else if ((buf[0] == 9) && + (buf[1] == 0x2B) && (buf[2] == 0x24) && + (buf[3] == 0x03) && (buf[4] == 0x03) && + (buf[5] == 0x02) && (buf[6] == 0x08) && + (buf[7] == 0x01) && (buf[8] == 0x01) && + (buf[9] == 0x07)) { + oid = ONAK_OID_BRAINPOOLP256R1; + /* brainpoolP384r1 / 1.3.36.3.3.2.8.1.1.11 */ + } else if ((buf[0] == 9) && + (buf[1] == 0x2B) && (buf[2] == 0x24) && + (buf[3] == 0x03) && (buf[4] == 0x03) && + (buf[5] == 0x02) && (buf[6] == 0x08) && + (buf[7] == 0x01) && (buf[8] == 0x01) && + (buf[9] == 0x0B)) { + oid = ONAK_OID_BRAINPOOLP384R1; + /* brainpoolP512r1 / 1.3.36.3.3.2.8.1.1.13 */ + } else if ((buf[0] == 9) && + (buf[1] == 0x2B) && (buf[2] == 0x24) && + (buf[3] == 0x03) && (buf[4] == 0x03) && + (buf[5] == 0x02) && (buf[6] == 0x08) && + (buf[7] == 0x01) && (buf[8] == 0x01) && + (buf[9] == 0x0D)) { + oid = ONAK_OID_BRAINPOOLP512R1; + /* secp256k1 / 1.3.132.0.10 */ + } else if ((buf[0] == 5) && + (buf[1] == 0x2B) && (buf[2] == 0x81) && + (buf[3] == 0x04) && (buf[4] == 0x00) && + (buf[5] == 0x0A)) { + oid = ONAK_OID_SECP256K1; + } else { + oid = ONAK_OID_UNKNOWN; + } + + return oid; +}