diff options
Diffstat (limited to 'usr/src/cmd/cmd-crypto/pktool/derparse.c')
-rw-r--r-- | usr/src/cmd/cmd-crypto/pktool/derparse.c | 371 |
1 files changed, 0 insertions, 371 deletions
diff --git a/usr/src/cmd/cmd-crypto/pktool/derparse.c b/usr/src/cmd/cmd-crypto/pktool/derparse.c deleted file mode 100644 index cec607220a..0000000000 --- a/usr/src/cmd/cmd-crypto/pktool/derparse.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * derparse.c - Functions for parsing DER-encoded data - * - * NOTE: This code was originally written by Cryptographic Products - * Group at Sun Microsystems for the SCA 1000 "realmparse" program. - * It is mostly intact except for necessary adaptaions to allow it to - * compile in this environment. - */ - -#include <errno.h> -#include <fcntl.h> -#include <lber.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <strings.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <cryptoutil.h> -#include "derparse.h" - -/* I18N helpers. */ -#include <libintl.h> -#include <locale.h> - -/* - * Some types that we need below. - */ -typedef struct oidinfo { - uint8_t *value; /* OID value in bytes */ - size_t length; /* Length of OID */ - char *strval; /* String rep. for OID in RDN */ -} oidinfo_t; - -/* - * X.509 Issuer OIDs as recommended by RFC 3280 - * We might see these in certificates in their subject an issuer names. - */ -static uint8_t common_name_oid[] = {0x55, 0x04, 0x03}; -static uint8_t surname_oid[] = {0x55, 0x04, 0x04}; -static uint8_t serial_number_oid[] = {0x55, 0x04, 0x05}; -static uint8_t country_name_oid[] = {0x55, 0x04, 0x06}; -static uint8_t locality_name_oid[] = {0x55, 0x04, 0x07}; -static uint8_t state_name_oid[] = {0x55, 0x04, 0x08}; -static uint8_t org_name_oid[] = {0x55, 0x04, 0x0a}; -static uint8_t org_unit_name_oid[] = {0x55, 0x04, 0x0b}; -static uint8_t title_oid[] = {0x55, 0x04, 0x0c}; -static uint8_t name_oid[] = {0x55, 0x04, 0x29}; -static uint8_t given_name_oid[] = {0x55, 0x04, 0x2a}; -static uint8_t initials_oid[] = {0x55, 0x04, 0x2b}; -static uint8_t gen_qual_oid[] = {0x55, 0x04, 0x2c}; -static uint8_t dn_qual_oid[] = {0x55, 0x04, 0x2e}; -static uint8_t pseudonym_oid[] = {0x55, 0x04, 0x31}; -static uint8_t uid_oid[] = - {0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x01}; -static uint8_t domain_comp_oid[] = - {0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19}; -static uint8_t email_addr_oid[] = - {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01}; - -/* Define this structure so we can match on a given oid */ -static oidinfo_t oids[] = { - {common_name_oid, sizeof (common_name_oid), "CN"}, - {surname_oid, sizeof (surname_oid), "SN"}, - {serial_number_oid, sizeof (serial_number_oid), "SerialNum"}, - {country_name_oid, sizeof (country_name_oid), "C"}, - {locality_name_oid, sizeof (locality_name_oid), "L"}, - {state_name_oid, sizeof (state_name_oid), "ST"}, - {org_name_oid, sizeof (org_name_oid), "O"}, - {org_unit_name_oid, sizeof (org_unit_name_oid), "OU"}, - {title_oid, sizeof (title_oid), "Title"}, - {name_oid, sizeof (name_oid), "Name"}, - {given_name_oid, sizeof (given_name_oid), "GN"}, - {initials_oid, sizeof (initials_oid), "Initials"}, - {gen_qual_oid, sizeof (gen_qual_oid), "GenQual"}, - {dn_qual_oid, sizeof (dn_qual_oid), "DNQual"}, - {pseudonym_oid, sizeof (pseudonym_oid), "Pseudonym"}, - {uid_oid, sizeof (uid_oid), "UID"}, - {domain_comp_oid, sizeof (domain_comp_oid), "DC"}, - {email_addr_oid, sizeof (email_addr_oid), "E"} -}; -static int oidblocklen = sizeof (oids) / sizeof (oidinfo_t); - -/* Local functions */ -static int oid_to_str(uint8_t *, size_t, char *, size_t); -static int get_oid_type(char *); - -/* - * An RDNSequence is what is handed to us when we get attributes like - * CKA_ISSUER and CKA_SUBJECT_NAME. This function will take in a buffer - * with the DER encoded bytes of an RDNSequence and print out the components. - * - * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName - * - * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue - * - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue - * } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - */ -void -rdnseq_to_str(uchar_t *derdata, size_t dersz, char *out, size_t outsz) -{ -#define PKTOOL_LINEMAX 1024 - char oidout[PKTOOL_LINEMAX]; - BerElement *ber = NULL; - BerValue ber_rdns; - int tag; - ber_len_t size; - char *atv_type = NULL; /* Attribute Type */ - ber_len_t atv_type_size; - char *atv_value = NULL; /* Attribute Value */ - ber_len_t atv_value_size; - char *cookie = NULL; - int idx; - char *prndata = NULL; - int prnsz; - int offset = 0; - boolean_t first = B_TRUE; - - cryptodebug("inside rdnseq_to_str"); - - if (derdata == NULL || dersz == 0) { - cryptodebug("nothing to parse"); - return; - } - - /* Take the raw bytes and stuff them into a BerValue structure */ - ber_rdns.bv_val = (char *)derdata; - ber_rdns.bv_len = dersz; - - /* Allocate the BerElement */ - if ((ber = ber_init(&ber_rdns)) == NULLBER) { - cryptodebug("ber_init failed to return ber element"); - cryptoerror(LOG_STDERR, gettext( - "Unable to begin parsing RDNSequence.")); - return; - } - - /* Begin by parsing out the outer sequence */ - tag = ber_next_element(ber, &size, cookie); - if (tag != LBER_SEQUENCE) { - cryptodebug("ber_next_element tag is not SEQUENCE"); - cryptoerror(LOG_STDERR, gettext( - "Expected RDNSequence SEQUENCE object, got tag [%02x]."), - tag); - return; - } - tag = ber_scanf(ber, "{"); - - /* Parse the sequence of RelativeDistinguishedName objects */ - while ((tag = ber_next_element(ber, &size, cookie)) != -1) { - if (tag != LBER_SET) { - cryptodebug("ber_next_element tag is not SET"); - cryptoerror(LOG_STDERR, gettext( - "Expected RelativeDistinguishedName SET object, " - "got tag [%02x]."), tag); - return; - } - tag = ber_scanf(ber, "["); - - /* AttributeTypeAndValue */ - tag = ber_next_element(ber, &size, cookie); - if (tag != LBER_SEQUENCE) { - cryptodebug("ber_next_element tag is not SEQUENCE"); - cryptoerror(LOG_STDERR, gettext( - "Expected AttributeTypeAndValue SEQUENCE object, " - "got tag [%02x]."), tag); - return; - } - tag = ber_scanf(ber, "{"); - - /* AttributeType OID */ - tag = ber_next_element(ber, &atv_type_size, cookie); - atv_type_size++; /* Add room for null terminator */ - if (tag != LBER_OID) { - cryptodebug("ber_next_element tag is not OID"); - cryptoerror(LOG_STDERR, gettext( - "Expected an OID, got tag [%02x]."), tag); - return; - } - /* Note: ber_scanf() allocates memory here for "a". */ - tag = ber_scanf(ber, "a", &atv_type, &atv_type_size); - - /* AttributeValue */ - tag = ber_next_element(ber, &atv_value_size, cookie); - atv_value_size++; - if ((tag != LBER_PRINTABLE_STRING) && (tag != LBER_IA5STRING)) { - cryptodebug("ber_next_element tag is not " - "PRINTABLE_STRING/IA5STRING"); - cryptoerror(LOG_STDERR, gettext("Expected a STRING, " - "got tag [%02x]."), tag); - free(atv_type); - return; - } - /* Note: ber_scanf() allocates memory here for "a". */ - tag = ber_scanf(ber, "a", &atv_value, &atv_value_size); - - /* - * Now go and turn the attribute type and value into - * some kind of meaningful output. - */ - if ((idx = get_oid_type(atv_type)) == -1) { - if (oid_to_str((uint8_t *)atv_type, strlen(atv_type), - oidout, sizeof (oidout)) < 0) { - cryptodebug("oid_to_str failed"); - cryptoerror(LOG_STDERR, gettext( - "Unable to convert OID to string.")); - free(atv_type); - free(atv_value); - return; - } - prndata = oidout; - } else { - prndata = oids[idx].strval; - } - - if (!first) - prnsz = snprintf(out + offset, outsz - offset, - ", %s = %s", prndata, atv_value); - else { - prnsz = snprintf(out + offset, outsz - offset, - "%s = %s", prndata, atv_value); - first = B_FALSE; - } - - free(atv_type); - free(atv_value); - atv_type = NULL; - atv_value = NULL; - - offset += prnsz; - if (offset >= outsz) - break; - } -} - -/* - * Convert OID to dotted notation string. - */ -static int -oid_to_str(uint8_t *oid, size_t oidlen, char *oidout, size_t oidout_len) -{ - int count = 0; - int offset = 0; - int prnsz; - uint_t firstnum; - uint_t secondnum; - uint64_t nextnum = 0; - - cryptodebug("inside oid_to_str"); - - if (oidlen == 0) - return (-1); - - /* - * The first octet has a value of (40 x oidnum1) + oidnum2. We - * will deconstruct it here and sanity check the result. According - * to X.690, oidnum1 should never be more than 2 and oidnum2 - * shouldn't be greater than 39 when oidnum1 = 0 or 1. - */ - firstnum = oid[count] / 40; - if (firstnum > 2) /* force remainder to be > 39 */ - firstnum = 2; - secondnum = oid[count] - (firstnum * 40); - - (void) memset(oidout, 0, oidout_len); - - prnsz = snprintf(oidout, oidout_len, "%d.%d", firstnum, secondnum); - offset += prnsz; - if (offset >= oidout_len) - return (0); - - /* Start at the second byte and move our way forward */ - for (count = 1; count < oidlen; count++) { - /* ORIGINAL COMMENT */ - /* - * Each oid byte is taken as a 7-bit number. If bit 8 is - * set, it means the next octet and this one are to be - * chained together as a single bit string, and so forth. - * We need to mask of bit 8, then shift over 7 bits in the - * resulting integer, and then stuff the new 7 bits in - * the low order byte, all the while making sure we don't - * stomp bit 1 from the previous octet. - * See X.690 or the layman's guide to ASN.1 for more. - */ - - /* - * String together as many of the next octets if each of - * their high order bits is set to 1. For example, - * 1 1010111, 1 0010100, 1 0010110, 0 1101111, ... - * (3 8-bit octets) - * becomes - * 1010111 0010100 0010110, 1101111, ... - * (one 21 bit integer) - * The high order bit functions as a "link" between octets. - * Note that if there are more than 9 octets with their - * high order bits set, it will overflow a 64-bit integer. - */ - for (nextnum = 0; (oid[count] & 0x80) && (count < oidlen); - count++) { - nextnum <<= 7; - nextnum |= (oid[count] & 0x7f); - } - if (count == oidlen) /* last number not terminated? */ - return (-1); - - /* We're done with this oid number, write it and move on */ - prnsz = snprintf(oidout + offset, oidout_len - offset, - ".%lld", nextnum); - offset += prnsz; - if (offset >= oidout_len) - return (0); - } - - return (0); -} - -/* - * Returns the index in the oids[] array that matches the input type, - * or -1 if it could not find a match. - */ -static int -get_oid_type(char *type) -{ - int count; - - cryptodebug("inside get_oid_type"); - - for (count = 0; count < oidblocklen; count++) { - if (memcmp(oids[count].value, type, oids[count].length) == 0) { - return (count); - } - } - - /* If we get here, we haven't found a match, so return -1 */ - return (-1); -} |