RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

p12util.c

Contains routines to manipulate data structures associated with PKCS #12 messages

/* $Id: p12util.c,v 1.3 2004/03/02 05:18:38 gsingh Exp $ */
/* p12util.c
** Copyright (c) 2000-2002, 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.
**
** This file contains routines that are useful in manipulating data
** structures associated with PKCS #12 messages.
*/

#include "p12util.h"
#include "certutil.h"
#include "crlutil.h"

int RSA_FormatPkcs12Password (char *asciiString, ITEM *pkcs12pwd)
{
  int status = 0;
  unsigned int i = 0;

  pkcs12pwd->len = (T_strlen (asciiString) + 1) * 2;
  pkcs12pwd->data = T_malloc (pkcs12pwd->len);
  if (pkcs12pwd->data == NULL) {
    status = RSA_DEMO_E_ALLOC;
    pkcs12pwd->len = 0;
    goto CLEANUP;
  }

  for (i = 0; i < pkcs12pwd->len; i += 2) {
    pkcs12pwd->data[i] = 0;
    pkcs12pwd->data[i+1] = asciiString[i/2];
  }

CLEANUP:
  if (status != 0)
    RSA_PrintError ("RSA_FormatPkcs12Password", status);
  
  return status;
}  /* end RSA_FormatPkcs12Password */

int RSA_Pkcs12EncryptionAlgPrompt (int *encAlg)
{
  int status = 0;
  RSA_DEMO_TABLE_ENTRY encAlgTable[6];
  RSA_DEMO_TABLE_ENTRY *result = NULL;

  encAlgTable[0].description = "3-Key Triple-DES CBC";
  encAlgTable[0].val.value = TRIPLE_DES_CBC_3KEY;
  encAlgTable[1].description = "2-Key Triple-DES CBC";
  encAlgTable[1].val.value = TRIPLE_DES_CBC_2KEY;
  encAlgTable[2].description = "128-bit RC4";
  encAlgTable[2].val.value = RC4_128BIT;
  encAlgTable[3].description = "40-bit RC4";
  encAlgTable[3].val.value = RC4_40BIT;
  encAlgTable[4].description = "128-bit RC2 CBC";
  encAlgTable[4].val.value = RC2_CBC_128BIT;
  encAlgTable[5].description = "40-bit RC2 CBC";
  encAlgTable[5].val.value = RC2_CBC_40BIT;

  RSA_PrintMessage ("Encryption Algorithms\n");

  status = ChooseTableEntryPrompt
             (encAlgTable, sizeof (encAlgTable) / sizeof (encAlgTable[0]),
              &result);
  if (status != 0)
    goto CLEANUP;

  *encAlg = (int)result->val.value;

CLEANUP:
  if (status != 0) {
    *encAlg = 0;
    RSA_PrintError ("RSA_Pkcs12EncryptionAlgPrompt", status);
  }

  return status;
}  /* end RSA_Pkcs12EncryptionAlgPrompt */

int RSA_Pkcs12FormatOptionsPrompt (int *option)
{
  int status = 0;
  RSA_DEMO_TABLE_ENTRY p12FormatTable[2];
  RSA_DEMO_TABLE_ENTRY *result = NULL;

  p12FormatTable[0].description = "PKCS12_MS_EXPLORER";
  p12FormatTable[0].val.value = PKCS12_MS_EXPLORER;
  p12FormatTable[1].description = "PKCS12_NS_NAVIGATOR";
  p12FormatTable[1].val.value = PKCS12_NS_NAVIGATOR;

  RSA_PrintMessage ("PKCS #12 Format Options\n");

  status = ChooseTableEntryPrompt
             (p12FormatTable,
              sizeof (p12FormatTable) / sizeof (p12FormatTable[0]), &result);
  if (status != 0)
    goto CLEANUP;

  *option = (int)result->val.value;

CLEANUP:
  if (status != 0) {
    *option = 0;
    RSA_PrintError ("RSA_Pkcs12FormatOptionsPrompt", status);
  }

  return status;
}  /* end RSA_Pkcs12FormatOptionsPrompt */

int RSA_Pkcs12BagInfoPrompt (CERTC_CTX ctx, LIST_OBJ pkcs12Bags)
{
  int status = 0;

  RSA_DEMO_TABLE_ENTRY p12BagTable[4];
  RSA_DEMO_TABLE_ENTRY *result = NULL;

  PKCS12_BAG pkcs12Bag;

  B_KEY_OBJ privateKey = NULL;
  CERT_OBJ certObj = NULL;
  CRL_OBJ crlObj = NULL;

  ITEM secretOid = {NULL, 0}, secretData = {NULL, 0}, octetString = {NULL, 0};

  p12BagTable[0].description = "Private Key";
  p12BagTable[0].val.value = PKCS12_KEY_BAG_TYPE;
  p12BagTable[1].description = "Certificate";
  p12BagTable[1].val.value = PKCS12_CERT_BAG_TYPE;
  p12BagTable[2].description = "CRL";
  p12BagTable[2].val.value = PKCS12_CRL_BAG_TYPE;
  p12BagTable[3].description = "Secret Content";
  p12BagTable[3].val.value = PKCS12_SECRET_BAG_TYPE;

  for (;;) {
    T_memset ((POINTER)&pkcs12Bag, 0, sizeof (pkcs12Bag));

    RSA_PrintMessage ("PKCS #12 Bag Types\n");

    status = ChooseTableEntryPrompt
               (p12BagTable, sizeof (p12BagTable) / sizeof (p12BagTable[0]),
                &result);
    if (status == RSA_DEMO_E_CANCEL) {
      status = 0;
      break;
    }
    else if (status != 0)
      break;

    pkcs12Bag.type = result->val.value;

    switch (pkcs12Bag.type) {
      case PKCS12_KEY_BAG_TYPE:
        status = C_CreateCertObject (&certObj, ctx);
        if (status != 0)
          break;

        status = B_CreateKeyObject (&privateKey);
        if (status != 0)
          break;

        RSA_PrintMessage ("Supply cert and matching private key.\n");
        status = RSA_GetCertAndPvtKey (ctx, certObj, privateKey);
        if (status != 0)
          break;

        pkcs12Bag.content.keyContent.key = privateKey;
        pkcs12Bag.content.keyContent.cert = certObj;
        break;
      case PKCS12_CERT_BAG_TYPE:
        status = C_CreateCertObject (&certObj, ctx);
        if (status != 0)
          break;

        status = RSA_GetCertObject (ctx, certObj, NULL);
        if (status != 0)
          break;

        pkcs12Bag.content.certContent = certObj;
        break;
      case PKCS12_CRL_BAG_TYPE:
        status = C_CreateCRLObject (&crlObj, ctx);
        if (status != 0)
          break;

        status = RSA_GetCrlObject (ctx, crlObj);
        if (status != 0)
          break;

        pkcs12Bag.content.crlContent = crlObj;
        break;
      case PKCS12_SECRET_BAG_TYPE:
        status = RSA_GetItem (&secretOid, "Enter hex-ascii object identifier");
        if (status != 0)
          break;

        pkcs12Bag.content.secretContent.type.data = secretOid.data;
        pkcs12Bag.content.secretContent.type.len = secretOid.len;
        
        /* For now, just wrap the secretValue in an OCTET STRING.  PKCS #12
           currently doesn't define any SecretTypes and corresponding value
           encodings. */
        status = RSA_GetFileToAllocBuffer
                   (&secretData.data, &secretData.len,
                    "Enter name of file containing associated value");
        if (status != 0)
          break;

        status = C_DEREncodeString (ctx, VT_OCTET_STRING, VTC_UNIVERSAL,
                                    secretData.data, secretData.len,
                                    &octetString.data, &octetString.len);

        pkcs12Bag.content.secretContent.value.data = octetString.data;
        pkcs12Bag.content.secretContent.value.len = octetString.len;
        
        break;
      default:
        RSA_PrintMessage ("Invalid value for PKCS12_BAG.type: %d\n",
                          pkcs12Bag.type);
        status = RSA_DEMO_E_INVALID_PARAMETER;
    }

    if (status != 0)
      break;

    /* optionally provide a value for the friendlyName field */
    pkcs12Bag.friendlyName.data = NULL;
    pkcs12Bag.friendlyName.len = 0;

    status = C_AddListObjectEntry (pkcs12Bags, (POINTER)&pkcs12Bag, NULL,
                                   &PKCS12BagEntryHandler);
    if (status != 0)
      break;

    B_DestroyKeyObject (&privateKey);
    C_DestroyCertObject (&certObj);
    C_DestroyCRLObject (&crlObj);

    T_free (secretOid.data);
    secretOid.data = NULL;
    
    T_memset (secretData.data, 0, secretData.len);
    T_free (secretData.data);
    secretData.data = NULL;

    T_memset (octetString.data, 0, octetString.len);
    T_free (octetString.data);
    octetString.data = NULL;
  } /* end loop adding entires to list object */

  if (status != 0)
    RSA_PrintError ("RSA_Pkcs12BagInfoPrompt", status);

  return status;
}  /* end RSA_Pkcs12BagInfoPrompt */

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