RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

Print Certificate Object Details

Utilities to print the contents of certificate objects, certificate request objects and X.509 v3 extensions.

/* $Id: myprint.c,v 1.6 2004/03/02 05:18:34 gsingh Exp $ */
/* myprint.c
** Copyright (c) 1995-2003, RSA Security Inc.
**
** This file is used to demonstrate how to interface to an RSA Security
** licensed development product.  You have a royalty-free right to use,
** modify, reproduce and distribute this demonstration file (including
** any modified version), provided that you agree that RSA Security has
** no warranty, implied or otherwise, or liability for this demonstration
** file or any modified version.
*/

#include <stdio.h>
#include "aglobal.h"
#include "bsafe.h"
#include "bcert.h" 
#include "dtime.h"
#include "dutil.h" 
#include "userextn.h"  
#include "myprint.h"
#include "inoutcl.h"

static char *GetExtensionType PROTO_LIST ((unsigned char *, unsigned int));
static int PrintExtensions PROTO_LIST ((EXTENSIONS_OBJ, char *));
static void PrintExtensionValue PROTO_LIST
  ((unsigned char *, unsigned int, POINTER));
static int PrintHex PROTO_LIST ((char *, unsigned char *, unsigned int));
static void PrintKeyUsage PROTO_LIST ((UINT4)); 

static void PrintPrivateKeyValidity PROTO_LIST ((PRIVATE_KEY_USAGE_PERIOD *));
static int PrintNameObject PROTO_LIST ((char *, NAME_OBJ));
static void PrintUINT4 PROTO_LIST ((char *, UINT4));

#ifdef _BCERT_API_
int PrintCertRequestObject (certRequestObject, message)   
CERT_REQUEST_OBJ certRequestObject;
char *message;
{
  CERT_REQUEST_FIELDS certRequestFields;
  ITEM der;
  int status;
  
  if (!certRequestObject)
    return (0);
  if ((status = C_GetCertRequestFields
       (certRequestObject, &certRequestFields)) != 0)
    return (status);
  if (message)
    puts (message);
  printf ("Version: %d\n", certRequestFields.version);
  PrintNameObject ("Subject Name: ", certRequestFields.subjectName);
  PrintHex 
    ("Public Key Info: ", certRequestFields.publicKey.data,
     certRequestFields.publicKey.len);  
  if (certRequestFields.attribute && (status = C_GetAttributesDER
    (certRequestFields.attribute, &der.data, &der.len)) == 0)
     PrintHex ("Attributes DER: ", der.data, der.len);

  return 0;
}
#else
int PrintPKCS10Object (pkcs10Object, message)   
PKCS10_OBJ pkcs10Object;
char *message;
{
  PKCS10_FIELDS pkcs10Fields;
  ITEM der;
  int status;
  
  if (!pkcs10Object)
    return (0);
  if ((status = C_GetPKCS10Fields
       (pkcs10Object, &pkcs10Fields)) != 0)
    return (status);
  if (message)
    puts (message);
  printf ("Version: %d\n", pkcs10Fields.version);
  PrintNameObject ("Subject Name: ", pkcs10Fields.subjectName);
  PrintHex 
    ("Public Key Info: ", pkcs10Fields.publicKey.data,
     pkcs10Fields.publicKey.len);  
  if (pkcs10Fields.attribute && (status = C_GetAttributesDER
    (pkcs10Fields.attribute, &der.data, &der.len)) == 0)
     PrintHex ("Attributes DER: ", der.data, der.len);

  return 0;
}
#endif /* _BCERT_API_ */

int PrintCertObject (certObject, message, ioContext)
CERT_OBJ certObject;
char *message;
IO_CTX_CL *ioContext;
{ 
  CERT_FIELDS certFields;
  char buffer[80];
  int status;

  UNUSED_ARG (ioContext);

  if (!certObject)
    return (0);
  if ((status = C_GetCertFields (certObject, &certFields)) != 0)
    return (status);
  if (message)
    puts (message);
  sprintf
    (buffer, "\nVersion: %d\nSignature Algorithm: %s\nSerial Number:",
     certFields.version, GetSignatureAlgorithmName
     (certFields.signatureAlgorithm)); 
  PrintHex
    (buffer, certFields.serialNumber.data, certFields.serialNumber.len);
  PrintNameObject ("Subject Name:", certFields.subjectName);
  PrintNameObject ("Issuer Name:", certFields.issuerName);
  PrintUINT4 ("Validity Start: ", certFields.validity.start);
  PrintUINT4 ("\nValidity End: ", certFields.validity.end);
  PrintHex
    ("\nPublic Key:", certFields.publicKey.data, certFields.publicKey.len);  
  if (certFields.issuerUniqueID.data != NULL_PTR)
    PrintHex 
      ("\nIssuer Unique ID: ", certFields.issuerUniqueID.data, 
       certFields.issuerUniqueID.len);
  if (certFields.subjectUniqueID.data != NULL_PTR)
    PrintHex 
      ("\nSubject Unique ID: ", certFields.subjectUniqueID.data, 
       certFields.subjectUniqueID.len); 
  if (certFields.certExtensions != (EXTENSIONS_OBJ)NULL_PTR) 
    PrintExtensions (certFields.certExtensions, "\nCertificate Extensions:");
  return (0);  
}            
             
static int PrintExtensions (extensionsObject, message)
EXTENSIONS_OBJ extensionsObject;
char *message;
{
  EXTENSION_INFO info;
  POINTER value;
  int status; 
  char buffer [256];
  unsigned int count, i, j;
  
  PRIVATE_KEY_USAGE_PERIOD *validity;
  
  if (!extensionsObject)
    return (0);
  if (message)
    puts (message);
  do {
    if ((status = C_GetExtensionCount (extensionsObject, &count)) != 0)
      break; 
    for (i = 0; i < count; ++i) {
      if ((status = C_GetExtensionInfo (extensionsObject, i, &info)) != 0)
        break;
      sprintf 
        (buffer, "\nType #%d: %s\nCriticality: %s", i+1, 
         GetExtensionType (info.type, info.typeLen), 
         (info.criticalFlag) ? "TRUE" : "FALSE");
      puts (buffer);  
      /* Print the extension value */
      for (j = 0; j < info.valueCount; ++j) {
        if ((status = C_GetExtensionValue
          (extensionsObject, i, j, &value)) != 0)
          break;  
        if (info.typeLen == ET_PRIVATE_KEY_USAGE_PERIOD_LEN)    
          validity = (PRIVATE_KEY_USAGE_PERIOD *)value;
        PrintExtensionValue (info.type, info.typeLen, value);
      } 
    }
  } while (0);
  return (status);
}                
                 
static void PrintExtensionValue (type, typeLen, value)
unsigned char *type;
unsigned int typeLen;
POINTER value;
{ 
  ITEM der;
  int status;
  
  if (typeLen == (unsigned int)USER_DEFINED_EXTENSION_LEN && 
    !T_memcmp ((POINTER)type, (POINTER)USER_DEFINED_EXTENSION, typeLen)) {
    if ((status = C_GetAttributesDER 
      ((ATTRIBUTES_OBJ)value, &der.data, &der.len)) == 0)
      PrintHex ("Extension Value: ", der.data, der.len);
    return;
  }
  else if ((typeLen == (unsigned int)ET_CRL_NUMBER_LEN) && 
           !T_memcmp ((POINTER)type, (POINTER)ET_CRL_NUMBER, typeLen)) {
    if ((status = C_GetAttributesDER 
      ((ATTRIBUTES_OBJ)value, &der.data, &der.len)) == 0)
      PrintHex ("Extension Value: ", der.data, der.len);
    return;
  }
  else if (typeLen == (unsigned int)ET_REASON_CODE_LEN && 
    !T_memcmp ((POINTER)type, (POINTER)ET_REASON_CODE, typeLen)) {
    puts ("Extension Value: ");
    switch (*(unsigned int *)value) {
      case CR_UNSPECIFIED:
        puts ("UNSPECIFIED");
        break;
      case CR_KEY_COMPROMISE:
        puts ("KEY_COMPROMISE");
        break;
      case CR_CA_COMPROMISE:
        puts ("CA_COMPROMISE");
        break;
      case CR_AFFILIATION_CHANGED:
        puts ("AFFILIATION_CHANGED");
        break;
      case CR_SUPERSEDED:
        puts ("SUPERSEDED");
        break;
      case CR_CESSATION_OF_OPERATION:
        puts ("CESSATION_OF_OPERATION");
        break;
      case CR_CERTIFICATE_HOLD:
        puts ("CERTIFICATE_HOLD");
        break;
      case CR_REMOVE_FROM_CRL:
        puts ("REMOVE_FROM_CRL");
        break;
    }
  }
  else if (typeLen == (unsigned int)ET_KEY_USAGE_LEN && 
    !T_memcmp ((POINTER)type, (POINTER)ET_KEY_USAGE, typeLen)) { 
    PrintKeyUsage (*(UINT4 *)value);
    return;
  }
  else if (typeLen == (unsigned int)ET_PRIVATE_KEY_USAGE_PERIOD_LEN && 
    !T_memcmp ((POINTER)type, (POINTER)ET_PRIVATE_KEY_USAGE_PERIOD, typeLen)) {
    PrintPrivateKeyValidity ((PRIVATE_KEY_USAGE_PERIOD *)value);
    return;
  }
  
  return;
}                 
                 
static void PrintPrivateKeyValidity (validity)
PRIVATE_KEY_USAGE_PERIOD *validity;
{  
  printf        
    ("Starting:\n\tYear: %d   Month: %d   Day: %d   Hour: %d\n", 
     validity->start.year, validity->start.month, validity->start.day, 
     validity->start.hour);
  printf        
    ("\tMinute: %d  Second: %d  Micro-second: %lu  Time zone: %hd\n", 
     validity->start.minute, validity->start.second, 
     validity->start.microSecond, validity->start.timeZone);   
     
  printf        
    ("Ending:\n\tYear: %d   Month: %d   Day: %d   Hour: %d\n", 
     validity->end.year, validity->end.month, validity->end.day,
     validity->end.hour);
  printf        
    ("\tMinute: %d  Second: %d  Micro-second: %lu  Time zone: %hd", 
     validity->end.minute, validity->end.second, validity->end.microSecond,
     validity->end.timeZone);
}         

static void PrintKeyUsage (keyUsage)
UINT4 keyUsage;
{ 
  printf 
    ("CF_DIGITAL_SIGNATURE: %s\n",
     (keyUsage & CF_DIGITAL_SIGNATURE) ? "YES" : "NO");
  printf 
    ("CF_KEY_CERT_SIGN: %s\n",
     (keyUsage & CF_KEY_CERT_SIGN) ? "YES" : "NO");
}

static char *GetExtensionType (type, typeLen)
unsigned char *type;
unsigned int typeLen;
{
  if (typeLen == USER_DEFINED_EXTENSION_LEN && !T_memcmp
    ((POINTER)type, (POINTER)USER_DEFINED_EXTENSION, typeLen))
    return ("User Defined Extensions");
  else if (typeLen == ET_KEY_USAGE_LEN && !T_memcmp
    ((POINTER)type, (POINTER)ET_KEY_USAGE, typeLen))
    return ("Key Usage"); 
  else if (typeLen == ET_PRIVATE_KEY_USAGE_PERIOD_LEN && !T_memcmp
    ((POINTER)type, (POINTER)ET_PRIVATE_KEY_USAGE_PERIOD, typeLen))
    return ("Private Key Usage Period");
  else if (typeLen == ET_CRL_NUMBER_LEN && !T_memcmp
    ((POINTER)type, (POINTER)ET_CRL_NUMBER, typeLen))
    return ("CRL Number");
  else if (typeLen == ET_REASON_CODE_LEN && !T_memcmp
    ((POINTER)type, (POINTER)ET_REASON_CODE, typeLen))
    return ("CRL Reason Code");
  else
    return ("Unknown type");
}

static int PrintHex (message, value, valueLen)
char *message;
unsigned char *value;
unsigned int valueLen;
{
  char *buffer = (char *)NULL_PTR;
  int status = 0;
  unsigned int len, i, j;

  if (value == NULL_PTR || valueLen == 0)
    return (0);
  do {
    len = valueLen * 3 + 1;
    buffer = (char *)T_malloc (len + 1);
    if (!buffer) {
      status = E_ALLOC;
      break;
    }
    T_memset ((POINTER)buffer, 0, len + 1);
    for (i = 0, j = 0; i < valueLen; ++i) {
      if (j  % 48 == 0) 
        *(buffer + j) = '\n';
      j++;
      sprintf (buffer + j, "%02x", *(value + i));
      j += 2;
      *(buffer + j) = ' ';
    }
    T_memcpy ((POINTER)buffer, (POINTER)buffer + 1, j - 1);
    *(buffer + j - 1) = '\n';
    *(buffer + j) = '\0';
    if (message != (char *)NULL_PTR)
      puts (message);
    printf (buffer);
  } while (0);
  T_free ((POINTER)buffer);
  return (status);  
}  

static int PrintNameObject (message, nameObject)
char *message;
NAME_OBJ nameObject;
{            
  ITEM type, value;
  int newLevel, status = 0, valueTag; 
  unsigned int count, i, j;
  
  if (message)
    puts (message);
  if ((status = C_GetNameAVACount (nameObject, &count)) != 0)
    return (status);
  for (i = 0; i < count; ++i) {
    if ((status = C_GetNameAVA 
      (nameObject, i, &type.data, &type.len, &valueTag, &value.data,
       &value.len, &newLevel)) != 0)
      break;
    if (valueTag == VT_PRINTABLE_STRING) {
      printf ("\t%s = ", GetAtttributeType (&type));
      /* Print characters one at a time.  printf() of value.data, even with 
         the precision specified as value.len, might read past the end of
         value.data.
       */
      for (j = 0; j < value.len; j++)
        putchar (value.data[j]);
      printf("\n");
    }
    else
      PrintHex (GetAtttributeType (&type), value.data, value.len);
  } 
  if (status)
    printf ("Error: %s\n", GetErrorMessage(status));
  return (status);
}

static void PrintUINT4 (message, uint4Time)
char *message;
UINT4 uint4Time;                    
{
  DATE printableTime;

  if (message != (char *)NULL_PTR)
    puts (message);
  TSecondsToDate (&printableTime, uint4Time); 
  printf
    ("%d/%d/%d - %d:%d:%d",
     printableTime.month, printableTime.day, printableTime.year,
     printableTime.hours, printableTime.minutes, printableTime.seconds);
}

Copyright (c) 1999-2005 RSA Security Inc. All rights reserved. 067-001001-2720-001-000 - 2.7.2