clasn1.c revision 02b8f7bbc995d1c58c013c6ae56040d8df009a4f
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1995-1999 Intel Corporation. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <strings.h>
#include <kmftypes.h>
#include <ber_der.h>
#include <kmfapi.h>
#include <kmfapiP.h>
#include <stdio.h>
#define DSA_RAW_SIG_LEN 40
static KMF_RETURN
{
}
return (KMF_ERR_BAD_CERT_FORMAT);
} else {
/*
* The algorithm data can be anything, so we just write it
* straight into the buffer. It is already DER encoded.
*/
}
}
return (ret);
}
static void
{
return;
}
static void
{
}
static void
{
}
}
static void
{
int i, j;
for (i = 0; i < name->numberOfRDNs; i++) {
for (j = 0; j < newrdn->numberOfPairs; j++) {
}
}
name->numberOfRDNs = 0;
}
}
static void
{
}
static void
{
}
}
static void
{
int i;
for (i = 0; i < extns->numberOfExtensions; i++) {
}
extns->numberOfExtensions = 0;
}
}
static void
{
if (tbscsr) {
}
}
static void
{
}
}
static void
{
if (tbscert) {
}
}
static void
{
if (!certptr)
return;
}
static KMF_RETURN
{
if (tag != BER_CONSTRUCTED_SEQUENCE)
return (KMF_ERR_BAD_CERT_FORMAT);
return (KMF_ERR_BAD_CERT_FORMAT);
}
} else {
/* Peek at the tag and length bytes */
goto cleanup;
}
/*
* We need to read the tag and the length bytes too,
* so adjust the size.
*/
goto cleanup;
}
/* read the raw data into the Algoritm params area. */
size) == -1) {
goto cleanup;
}
}
}
}
return (ret);
}
static KMF_RETURN
{
return (KMF_ERR_MEMORY);
}
return (KMF_OK);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_CERT_FORMAT);
return (ret);
return (KMF_ERR_BAD_CERT_FORMAT);
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
return (ret);
}
return (KMF_ERR_ENCODING);
}
return (KMF_OK);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_CERT_FORMAT);
return (ret);
} else {
goto cleanup;
}
}
return (ret);
}
{
int n;
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_BAD_PARAMETER);
asn1 = kmfder_alloc();
return (KMF_ERR_MEMORY);
/*
* The DSA signature is the concatenation of 2 SHA-1 hashed
* bignum values.
*/
n = DSA_RAW_SIG_LEN/2;
return (KMF_ERR_MEMORY);
}
return (KMF_ERR_ENCODING);
}
return (KMF_OK);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
goto cleanup;
}
goto cleanup;
}
if (R && R->bv_val)
if (S && S->bv_val)
if (S) free(S);
if (R) free(R);
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
}
return (ret);
}
{
return (KMF_ERR_MEMORY);
goto cleanup;
goto cleanup;
goto cleanup;
if (newspki)
}
return (ret);
}
static KMF_RETURN
{
int ret;
if (ret == -1)
return (KMF_ERR_BAD_CERT_FORMAT);
return (KMF_OK);
}
static KMF_RETURN
{
int tag;
if (tag != BER_CONSTRUCTED_SEQUENCE) {
return (KMF_ERR_BAD_CERT_FORMAT);
}
return (KMF_ERR_BAD_CERT_FORMAT);
}
return (ret);
}
{
/* Add new RDN record to existing list */
name->numberOfRDNs++;
goto cleanup;
}
if (newrdn) {
} else {
rdnslot->numberOfPairs = 0;
}
/* No cleanup needed here */
return (ret);
}
static KMF_RETURN
{
int i;
goto cleanup;
}
for (i = 0; i < name->numberOfRDNs; i++) {
goto cleanup;
}
if (rdn->numberOfPairs > 0) {
&attrtvpair->type,
goto cleanup;
}
}
goto cleanup;
}
}
goto cleanup;
}
/* No cleanup needed here */
return (ret);
}
{
int i, j;
return (KMF_ERR_MEMORY);
sizeof (KMF_X509_RDN));
return (KMF_ERR_MEMORY);
}
/* Copy each RDN in the list */
for (i = 0; i < newname->numberOfRDNs; i++) {
if (dstrdn->numberOfPairs > 0) {
sizeof (KMF_X509_TYPE_VALUE_PAIR));
goto cleanup;
}
sizeof (KMF_X509_TYPE_VALUE_PAIR));
goto cleanup;
}
/* Copy each A/V pair in the list */
for (j = 0; j < dstrdn->numberOfPairs; j++) {
goto cleanup;
goto cleanup;
}
} else {
}
}
if (newname)
}
return (ret);
}
#define VALID_DIRECTORYSTRING_TAG(t) ( \
(t == BER_UTF8_STRING) || \
(t == BER_PRINTABLE_STRING) || \
(t == BER_IA5STRING) || \
(t == BER_T61STRING) || \
(t == BER_BMP_STRING) || \
(t == BER_UNIVERSAL_STRING))
static KMF_RETURN
{
char *end;
int tag;
/*
* AttributeType ::= OBJECT IDENTIFIER
* AttributeValue ::= ANY
*
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
*
* Name ::= CHOICE { -- only one possibility for now --
* rdnSequence RDNSequence }
*
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
*
* DistinguishedName ::= RDNSequence
*
* RelativeDistinguishedName ::=
* SET SIZE (1 .. MAX) OF AttributeTypeAndValue
*
*/
name->numberOfRDNs = 0;
/* Get the beginning of the RDN Set and a ptr to the end */
if (tag != BER_CONSTRUCTED_SET) {
goto cleanup;
}
/* Walk through the individual SET items until the "end" is reached */
/* Skip over the SET tag */
break;
}
/* An "empty" set member means we tack on an empty node */
if (size == 0) {
goto cleanup;
continue;
}
/* Attr OID and peek at the next tag and field length */
break;
}
if (!(VALID_DIRECTORYSTRING_TAG(tag))) {
break;
}
break;
}
break;
}
break;
}
}
return (ret);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
return (KMF_OK);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
return (KMF_OK);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_CERT_FORMAT);
return (ret);
}
static KMF_RETURN
{
int i;
for (i = 0; i < extns->numberOfExtensions; i++) {
BerValue v;
goto cleanup;
}
goto cleanup;
}
}
goto cleanup;
}
}
return (ret);
}
static KMF_RETURN
{
extn = kmfder_alloc();
return (KMF_ERR_MEMORY);
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
return (ret);
}
static KMF_RETURN
{
goto cleanup;
}
if (tag != BER_OBJECT_IDENTIFIER) {
goto cleanup;
}
goto cleanup;
}
if (tag != BER_BOOLEAN) {
critical = 0;
if (tag != BER_OCTET_STRING)
goto cleanup;
} else {
goto cleanup;
}
if (tag != BER_OCTET_STRING) {
goto cleanup;
}
goto cleanup;
}
/* allocate a new Extension record */
goto cleanup;
}
/* Tag and value is a little tricky */
goto cleanup;
}
sizeof (KMF_X509EXT_TAGandVALUE));
/* Parse the Extension value field */
goto cleanup;
}
/* Get the tag and length of the extension field */
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
}
return (ret);
}
static KMF_RETURN
{
/*
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
*
* Extension ::= SEQUENCE {
* extnID OBJECT IDENTIFIER,
* critical BOOLEAN DEFAULT FALSE,
* extnValue OCTET STRING }
*
* { {{D}Bo}, ... }
*/
return (KMF_ERR_BAD_CERT_FORMAT);
goto cleanup;
sizeof (KMF_X509_EXTENSION));
break;
}
}
return (ret);
}
{
goto cleanup;
}
/* Version number is optional */
if (tag == 0xA0) {
goto cleanup;
}
} else {
version = 0; /* DEFAULT v1 (0) */
}
/* Now get the serial number, it is not optional */
goto cleanup;
} else {
}
if (!tbscert) {
goto cleanup;
}
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
/* Check for the optional fields */
char *optfield;
/* consume the tag and length */
switch (tag) {
case 0xA1:
goto cleanup;
}
len / 8;
break;
case 0xA2:
goto cleanup;
}
len / 8;
break;
case 0xA3:
break;
}
}
}
if (tbscert) {
}
}
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
goto cleanup;
if (newcert)
}
return (ret);
}
/*
* Name: DerDecodeSignedCertificate
*
* Description:
* DER decodes the encoded X509 certificate
*
* Parameters:
* Value (input): DER encoded object that shd be decoded
*
* signed_cert_ptr_ptr (output) : Decoded KMF_X509_CERTIFICATE object
*/
{
char *signature;
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
goto cleanup;
}
goto cleanup;
}
goto cleanup;
/*
* The signature data my not be present yet.
*/
/* Check to see if the cert has a signature yet */
/* Finally, get the encrypted signature BITSTRING */
goto cleanup;
}
if (tag != BER_BIT_STRING) {
goto cleanup;
}
goto cleanup;
}
} else {
}
} else {
}
if (certptr) {
}
}
if (asn1)
return (ret);
}
{
return (KMF_ERR_MEMORY);
}
}
return (ret);
}
{
return (KMF_ERR_MEMORY);
goto cleanup;
if (asn1)
return (ret);
}
{
asn1 = kmfder_alloc();
return (KMF_ERR_MEMORY);
goto cleanup;
goto cleanup;
}
if (bv)
if (asn1)
return (ret);
}
static KMF_RETURN
{
/* version should be 4 bytes or less */
return (KMF_ERR_BAD_CERT_FORMAT);
/* Start the sequence and add the version */
goto cleanup;
}
/* Write the serial number */
goto cleanup;
}
goto cleanup;
/* Encode the Issuer RDN */
goto cleanup;
/* Encode the Validity fields */
goto cleanup;
/* Encode the Subject RDN */
goto cleanup;
/* Encode the Subject Public Key Info */
goto cleanup;
/* Optional field: issuer Unique ID */
goto cleanup;
}
/* Optional field: Subject Unique ID */
goto cleanup;
}
/* Optional field: Certificate Extensions */
goto cleanup;
}
/* Close out the TBSCert sequence */
goto cleanup;
}
/*
* Memory cleanup is done in the caller or in the individual
* encoding routines.
*/
return (ret);
}
{
asn1 = kmfder_alloc();
return (KMF_ERR_MEMORY);
enc_tbs_cert_ptr->Length = 0;
goto cleanup;
goto cleanup;
}
if (tbsdata)
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
encodedcert->Length = 0;
asn1 = kmfder_alloc();
return (KMF_ERR_MEMORY);
/* Start outer X509 Certificate SEQUENCE */
goto cleanup;
}
goto cleanup;
}
/* Add the Algorithm & Signature Sequence */
goto cleanup;
goto cleanup;
}
}
goto cleanup;
}
goto cleanup;
}
if (tbsdata)
if (asn1)
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
/* Skip over the overall Sequence tag to get at the TBS Cert data */
goto cleanup;
}
if (tag != BER_CONSTRUCTED_SEQUENCE) {
goto cleanup;
}
/*
* Since we are extracting a copy of the ENCODED bytes, we
* must make sure to also include the bytes for the tag and
* the length fields for the CONSTRUCTED SEQUENCE (TBSCert).
*/
goto cleanup;
}
/* The der data ptr is now set to the start of the TBS cert sequence */
goto cleanup;
}
goto cleanup;
goto cleanup;
}
/* Now get the signature data */
goto cleanup;
}
/* convert bitstring length to bytes */
}
if (der)
return (ret);
}
/*
* Name: GetKeyFromSpki
*
* Description:
* This function parses the KMF_X509_SPKI into its
* key and parameter components based on the key generation algorithm.
* NOTE: Currently, it only checks for the RSA and DSA algorithms.
* The RSA algorithm is equivalent to the default behavior.
* All other algorithms will default to the parameters = NULL and the
* key data equal to whatever is in the CSSM_KEY structure for the key
*
* Parameters:
* AlgId (input) : Algorithm identifier
* SpkiPtr (input): SPKI structure that contains the key
* key_ptr(output): The output key
*
*/
{
return (KMF_ERR_BAD_PARAMETER);
}
switch (AlgId) {
case KMF_ALGID_DSA:
asn1 = kmfder_alloc();
return (KMF_ERR_MEMORY);
}
goto cleanup;
}
goto cleanup;
}
if (!*key_ptr) {
goto cleanup;
}
if (encodedkey)
break;
default: /* RSA */
if (!*key_ptr) {
return (KMF_ERR_MEMORY);
}
return (KMF_ERR_MEMORY);
}
return (ret);
}
return (ret);
}
static KMF_RETURN
{
return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
}
/* We only understand extension requests in a CSR */
return (KMF_ERR_UNKNOWN_CSR_ATTRIBUTE);
}
return (KMF_ERR_ENCODING);
}
return (ret);
}
static KMF_RETURN
{
/* Now get the version number, it is not optional */
goto cleanup;
}
if (!tbscsr) {
goto cleanup;
}
goto cleanup;
goto cleanup;
goto cleanup;
/* Check for the optional fields (attributes) */
goto cleanup;
}
}
if (tbscsr) {
}
}
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
goto cleanup;
if (newcsr)
}
return (ret);
}
{
int tag;
char *signature;
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
goto cleanup;
}
goto cleanup;
}
goto cleanup;
goto cleanup;
/* Check to see if the cert has a signature yet */
/* Finally, get the encrypted signature BITSTRING */
goto cleanup;
}
if (tag != BER_BIT_STRING) {
goto cleanup;
}
goto cleanup;
}
} else {
}
if (csrptr)
}
if (asn1)
return (ret);
}
static KMF_RETURN
{
int attlen = 0;
/* Optional field: CSR attributes and extensions */
goto cleanup;
}
} else {
/* No extensions or attributes to encode */
return (KMF_OK);
}
/*
* attributes [0] Attributes
* Attributes := SET OF Attribute
* Attribute := SEQUENCE {
* { ATTRIBUTE ID
* values SET SIZE(1..MAX) of ATTRIBUTE
* }
*
* Ex: { ExtensionRequest OID [ { {extn1 } , {extn2 } } ] }
*/
/*
* Encode any extensions and add to the attributes section.
*/
extnasn1 = kmfder_alloc();
goto cleanup;
}
&extension_request_oid) == -1) {
goto cleanup_1;
}
goto cleanup_1;
}
goto cleanup_1;
}
goto cleanup_1;
}
/* Add 2 bytes to cover the tag and the length */
}
goto cleanup;
goto cleanup;
}
/* Write the actual encoded extensions */
goto cleanup;
}
}
/*
* Memory cleanup is done in the caller or in the individual
* encoding routines.
*/
if (extnvalue) {
}
return (ret);
}
static KMF_RETURN
{
/* Start the version */
goto cleanup;
}
/* Encode the Subject RDN */
goto cleanup;
/* Encode the Subject Public Key Info */
goto cleanup;
goto cleanup;
/* Close out the TBSCert sequence */
goto cleanup;
}
return (ret);
}
{
asn1 = kmfder_alloc();
return (KMF_ERR_MEMORY);
rv = KMF_ERR_MEMORY;
goto cleanup;
}
rv = KMF_ERR_MEMORY;
goto cleanup;
}
return (rv);
}
{
asn1 = kmfder_alloc();
return (KMF_ERR_MEMORY);
&ver, 1,
goto cleanup;
rv = KMF_ERR_MEMORY;
goto cleanup;
}
return (rv);
}
{
asn1 = kmfder_alloc();
enc_tbs_csr_ptr->Length = 0;
return (KMF_ERR_MEMORY);
goto cleanup;
goto cleanup;
}
if (tbsdata)
return (ret);
}
{
if (signed_csr_ptr == NULL)
return (KMF_ERR_BAD_PARAMETER);
asn1 = kmfder_alloc();
return (KMF_ERR_MEMORY);
/* Start outer CSR SEQUENCE */
goto cleanup;
}
/* Add the Algorithm & Signature Sequence */
goto cleanup;
goto cleanup;
}
}
goto cleanup;
}
goto cleanup;
}
}
if (tbsdata)
if (asn1)
return (ret);
}
const KMF_X509_SPKI *pKey,
{
return (KMF_ERR_BAD_PARAMETER);
switch (AlgorithmId) {
case KMF_ALGID_DSA:
case KMF_ALGID_SHA1WithDSA:
/* First, get the parameters from the algorithm definition */
return (KMF_ERR_MEMORY);
return (KMF_ERR_BAD_KEY_FORMAT);
}
free(P);
free(Q);
free(G);
/* Get the PubKey data */
goto cleanup;
}
goto cleanup;
}
break;
case KMF_ALGID_RSA:
case KMF_ALGID_MD2WithRSA:
case KMF_ALGID_MD5WithRSA:
case KMF_ALGID_SHA1WithRSA:
goto cleanup;
}
goto cleanup;
}
break;
default:
return (KMF_ERR_BAD_PARAMETER);
}
int i;
for (i = 0; i < *uNumKeyParts; i++)
}
}
return (ret);
}