Example #1
0
void NSSCryptoKeyRSA::loadParamsFromKey(void) {

	if (mp_pubkey == 0)
			return;

  mp_modulus = SECITEM_DupItem(&(mp_pubkey->u.rsa.modulus));

  if (mp_modulus == 0)
  {

    throw XSECCryptoException(XSECCryptoException::RSAError,
			"NSS:RSA - Error during extracting modulus from public key");
 
  }

  mp_exponent = SECITEM_DupItem(&(mp_pubkey->u.rsa.publicExponent));

  if (mp_exponent == 0)
  {

    throw XSECCryptoException(XSECCryptoException::RSAError,
			"NSS:RSA - Error during extracting exponent from public key");

  }
}
Example #2
0
XSECCryptoKey * NSSCryptoKeyRSA::clone() const {

	NSSCryptoKeyRSA * ret;

	XSECnew(ret, NSSCryptoKeyRSA(mp_pubkey, mp_privkey));
	
	if (mp_pubkey != 0) {

    ret->mp_pubkey = SECKEY_CopyPublicKey(mp_pubkey);
  
    if (ret->mp_pubkey == 0) {

      throw XSECCryptoException(XSECCryptoException::MemoryError,
		    "NSS:RSA Error attempting to clone (copy) public key");

    }

  }

  if (mp_privkey != 0) {

    ret->mp_privkey = SECKEY_CopyPrivateKey(mp_privkey);

    if (ret->mp_privkey == 0) {

      throw XSECCryptoException(XSECCryptoException::MemoryError,
		    "NSS:RSA Error attempting to clone (copy) private key");

    }

  }

  // Clone modulus
  if (mp_modulus != 0) {
    ret->mp_modulus = SECITEM_DupItem(mp_modulus);

    if (ret->mp_modulus == 0) {

      throw XSECCryptoException(XSECCryptoException::MemoryError,
	  	  "NSS:RSA Error attempting to clone (copy) modulus");

    }
  }

  // Clone exponent
  if (mp_exponent != 0) {
    ret->mp_exponent = SECITEM_DupItem(mp_exponent);

    if (ret->mp_exponent == 0) {

      throw XSECCryptoException(XSECCryptoException::MemoryError,
		    "NSS:RSA Error attempting to clone (copy) exponent");

    }
  }

  return ret;

}
Example #3
0
SECItem *
CRMF_EncryptedValueGetValueHint(CRMFEncryptedValue *inEncValue)
{
    if (inEncValue == NULL || inEncValue->valueHint.data == NULL) {
        return NULL;
    }
    return SECITEM_DupItem(&inEncValue->valueHint);
}
Example #4
0
SECItem *
CRMF_POPOSigningKeyGetInput(CRMFPOPOSigningKey *inSignKey)
{
    PORT_Assert(inSignKey != NULL);
    if (inSignKey == NULL || inSignKey->derInput.data == NULL) {
        return NULL;
    }
    return SECITEM_DupItem(&inSignKey->derInput);
}
Example #5
0
SECItem *
CRMF_PKIArchiveOptionsGetKeyGenParameters(CRMFPKIArchiveOptions *inOptions)
{
    if (inOptions == NULL ||
        CRMF_PKIArchiveOptionsGetOptionType(inOptions) != crmfKeyGenParameters ||
        inOptions->option.keyGenParameters.data == NULL) {
        return NULL;
    }
    return SECITEM_DupItem(&inOptions->option.keyGenParameters);
}
Example #6
0
/*
 * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h)
 */
PKIX_Error *
PKIX_PL_CRL_Create(
        PKIX_PL_ByteArray *byteArray,
        PKIX_PL_CRL **pCrl,
        void *plContext)
{
        CERTSignedCrl *nssSignedCrl = NULL;
        SECItem derItem, *derCrl = NULL;
        PKIX_PL_CRL *crl = NULL;

        PKIX_ENTER(CRL, "PKIX_PL_CRL_Create");
        PKIX_NULLCHECK_TWO(byteArray, pCrl);

        if (byteArray->length == 0){
            PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING);
        }
        derItem.type = siBuffer;
        derItem.data = byteArray->array;
        derItem.len = byteArray->length;
        derCrl = SECITEM_DupItem(&derItem);
        if (!derCrl) {
            PKIX_ERROR(PKIX_ALLOCERROR);
        }
        nssSignedCrl =
            CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE,
                                       CRL_DECODE_DONT_COPY_DER |
                                       CRL_DECODE_SKIP_ENTRIES);
        if (!nssSignedCrl) {
            PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED);
        }
        PKIX_CHECK(
            pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL,
                                            &crl, plContext),
            PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
        nssSignedCrl = NULL;
        derCrl = NULL;
        *pCrl = crl;

cleanup:
        if (derCrl) {
            SECITEM_FreeItem(derCrl, PR_TRUE);
        }
        if (nssSignedCrl) {
            SEC_DestroyCrl(nssSignedCrl);
        } 

        PKIX_RETURN(CRL);
}
Example #7
0
/*
 * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL
 * DESCRIPTION:
 *
 *  Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl"
 *  and stores it at "pCRL". If the decoding of the CERTSignedCrl fails,
 *  a PKIX_Error is returned.
 *
 * PARAMETERS:
 *  "nssSignedCrl"
 *      Address of CERTSignedCrl. Must be non-NULL.
 *  "adoptedDerCrl"
 *      SECItem ponter that if not NULL is indicating that memory used
 *      for der should be adopted by crl that is about to be created.
 *  "pCRL"
 *      Address where object pointer will be stored. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a CRL Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */
PKIX_Error *
pkix_pl_CRL_CreateWithSignedCRL(
        CERTSignedCrl *nssSignedCrl,
        SECItem *adoptedDerCrl,
        SECItem *derGenName,
        PKIX_PL_CRL **pCrl,
        void *plContext)
{
        PKIX_PL_CRL *crl = NULL;

        PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL");
        PKIX_NULLCHECK_ONE(pCrl);

        /* create a PKIX_PL_CRL object */
        PKIX_CHECK(PKIX_PL_Object_Alloc
                    (PKIX_CRL_TYPE,
                    sizeof (PKIX_PL_CRL),
                    (PKIX_PL_Object **)&crl,
                    plContext),
                    PKIX_COULDNOTCREATECRLOBJECT);

        /* populate the nssSignedCrl field */
        crl->nssSignedCrl = nssSignedCrl;
        crl->adoptedDerCrl = adoptedDerCrl;
        crl->issuer = NULL;
        crl->signatureAlgId = NULL;
        crl->crlNumber = NULL;
        crl->crlNumberAbsent = PKIX_FALSE;
        crl->crlEntryList = NULL;
        crl->critExtOids = NULL;
        if (derGenName) {
            crl->derGenName =
                SECITEM_DupItem(derGenName);
            if (!crl->derGenName) {
                PKIX_ERROR(PKIX_ALLOCERROR);
            }
        }

        *pCrl = crl;

cleanup:

        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(crl);
        }

        PKIX_RETURN(CRL);
}
Example #8
0
SECItem *
SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
{
    SECItem *sniName = NULL;
    sslSocket *ss;
    char *name = NULL;

    ss = ssl_FindSocket(fd);
    if (!ss) {
        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNegotiatedHostInfo",
                 SSL_GETPID(), fd));
        return NULL;
    }

    if (ss->sec.isServer) {
        if (ss->version > SSL_LIBRARY_VERSION_3_0 &&
            ss->ssl3.initialized) { /* TLS */
            SECItem *crsName;
            ssl_GetSpecReadLock(ss); /*********************************/
            crsName = &ss->ssl3.hs.srvVirtName;
            if (crsName->data) {
                sniName = SECITEM_DupItem(crsName);
            }
            ssl_ReleaseSpecReadLock(ss); /*----------------------------*/
        }
        return sniName;
    }
    name = SSL_RevealURL(fd);
    if (name) {
        sniName = PORT_ZNew(SECItem);
        if (!sniName) {
            PORT_Free(name);
            return NULL;
        }
        sniName->data = (void *)name;
        sniName->len = PORT_Strlen(name);
    }
    return sniName;
}
Example #9
0
SECStatus
cmmf_CertOrEncCertSetCertificate(CMMFCertOrEncCert *certOrEncCert,
                                 PLArenaPool *poolp,
                                 CERTCertificate *inCert)
{
    SECItem *derDest = NULL;
    SECStatus rv = SECFailure;

    if (inCert->derCert.data == NULL) {
        derDest = SEC_ASN1EncodeItem(NULL, NULL, inCert,
                                     CMMFCertOrEncCertCertificateTemplate);
        if (derDest == NULL) {
            goto loser;
        }
    } else {
        derDest = SECITEM_DupItem(&inCert->derCert);
        if (derDest == NULL) {
            goto loser;
        }
    }
    PORT_Assert(certOrEncCert->cert.certificate == NULL);
    certOrEncCert->cert.certificate = CERT_DupCertificate(inCert);
    certOrEncCert->choice = cmmfCertificate;
    if (poolp != NULL) {
        rv = SECITEM_CopyItem(poolp, &certOrEncCert->derValue, derDest);
        if (rv != SECSuccess) {
            goto loser;
        }
    } else {
        certOrEncCert->derValue = *derDest;
    }
    PORT_Free(derDest);
    return SECSuccess;
loser:
    if (derDest != NULL) {
        SECITEM_FreeItem(derDest, PR_TRUE);
    }
    return rv;
}
Example #10
0
/*
 * Common Helper Function do come up with a new context.
 */
static PK11Context *pk11_CreateNewContextInSlot(CK_MECHANISM_TYPE type,
        PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey,
        SECItem *param)
{
    CK_MECHANISM mech_info;
    PK11Context *context;
    SECStatus rv;

    PORT_Assert(slot != NULL);
    if (!slot || (!symKey && operation != CKA_DIGEST)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }
    context = (PK11Context *) PORT_Alloc(sizeof(PK11Context));
    if (context == NULL) {
        return NULL;
    }

    /* now deal with the fortezza hack... the fortezza hack is an attempt
     * to get around the issue of the card not allowing you to do a FORTEZZA
     * LoadIV/Encrypt, which was added because such a combination could be
     * use to circumvent the key escrow system. Unfortunately SSL needs to
     * do this kind of operation, so in SSL we do a loadIV (to verify it),
     * Then GenerateIV, and through away the first 8 bytes on either side
     * of the connection.*/
    context->fortezzaHack = PR_FALSE;
    if (type == CKM_SKIPJACK_CBC64) {
        if (symKey->origin == PK11_OriginFortezzaHack) {
            context->fortezzaHack = PR_TRUE;
        }
    }

    /* initialize the critical fields of the context */
    context->operation = operation;
    context->key = symKey ? PK11_ReferenceSymKey(symKey) : NULL;
    context->slot = PK11_ReferenceSlot(slot);
    context->session = pk11_GetNewSession(slot,&context->ownSession);
    context->cx = symKey ? symKey->cx : NULL;
    /* get our session */
    context->savedData = NULL;

    /* save the parameters so that some digesting stuff can do multiple
     * begins on a single context */
    context->type = type;
    if (param) {
        if (param->len > 0) {
            context->param = SECITEM_DupItem(param);
        } else {
            context->param = (SECItem *)&pk11_null_params;
        }
    } else {
        context->param = NULL;
    }
    context->init = PR_FALSE;
    context->sessionLock = PZ_NewLock(nssILockPK11cxt);
    if ((context->param == NULL) || (context->sessionLock == NULL)) {
        PK11_DestroyContext(context,PR_TRUE);
        return NULL;
    }

    mech_info.mechanism = type;
    mech_info.pParameter = param->data;
    mech_info.ulParameterLen = param->len;
    PK11_EnterContextMonitor(context);
    rv = pk11_context_init(context,&mech_info);
    PK11_ExitContextMonitor(context);

    if (rv != SECSuccess) {
        PK11_DestroyContext(context,PR_TRUE);
        return NULL;
    }
    context->init = PR_TRUE;
    return context;
}
/*
 * FUNCTION: pkix_pl_LdapCertStore_BuildCrlList
 * DESCRIPTION:
 *
 *  This function takes a List of LdapResponse objects pointed to by
 *  "responseList" and extracts and decodes the CRLs in those responses, storing
 *  the List of those CRLs at "pCrls". If none of the objects can be decoded
 *  into a CRL, the returned List is empty.
 *
 * PARAMETERS:
 *  "responseList"
 *      The address of the List of LdapResponses. Must be non-NULL.
 *  "pCrls"
 *      The address at which the result is stored. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a CertStore Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */
PKIX_Error *
pkix_pl_LdapCertStore_BuildCrlList(
        PKIX_List *responseList,
        PKIX_List **pCrls,
        void *plContext)
{
        PKIX_UInt32 numResponses = 0;
        PKIX_UInt32 respIx = 0;
        LdapAttrMask attrBits = 0;
        CERTSignedCrl *nssCrl = NULL;
        PKIX_PL_LdapResponse *response = NULL;
        PKIX_List *crlList = NULL;
        PKIX_PL_CRL *crl = NULL;
        LDAPMessage *message = NULL;
        LDAPSearchResponseEntry *sre = NULL;
        LDAPSearchResponseAttr **sreAttrArray = NULL;
        LDAPSearchResponseAttr *sreAttr = NULL;
        SECItem *attrType = NULL;
        SECItem **attrVal = NULL;
        SECItem *derCrlCopy = NULL;
        SECItem *derCrlItem = NULL;

        PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCrlList");
        PKIX_NULLCHECK_TWO(responseList, pCrls);

        PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
                PKIX_LISTCREATEFAILED);

        /* extract crls from response */
        PKIX_CHECK(PKIX_List_GetLength
                (responseList, &numResponses, plContext),
                PKIX_LISTGETLENGTHFAILED);

        for (respIx = 0; respIx < numResponses; respIx++) {
                PKIX_CHECK(PKIX_List_GetItem
                        (responseList,
                        respIx,
                        (PKIX_PL_Object **)&response,
                        plContext),
                        PKIX_LISTGETITEMFAILED);

                PKIX_CHECK(pkix_pl_LdapResponse_GetMessage
                        (response, &message, plContext),
                        PKIX_LDAPRESPONSEGETMESSAGEFAILED);

                sre = &(message->protocolOp.op.searchResponseEntryMsg);
                sreAttrArray = sre->attributes;

                /* Get next element of null-terminated array */
                sreAttr = *sreAttrArray++;
                while (sreAttr != NULL) {
                    attrType = &(sreAttr->attrType);
                    PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit
                        (attrType, &attrBits, plContext),
                        PKIX_LDAPREQUESTATTRTYPETOBITFAILED);
                    /* Is this attrVal a Revocation List? */
                    if (((LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST) &
                            attrBits) == attrBits) {
                        attrVal = sreAttr->val;
                        derCrlItem = *attrVal++;
                        while (derCrlItem != 0) {
                            /* create a PKIX_PL_Crl from derCrl */
                            derCrlCopy = SECITEM_DupItem(derCrlItem);
                            if (!derCrlCopy) {
                                PKIX_ERROR(PKIX_ALLOCERROR);
                            }
                            /* crl will be based on derCrlCopy, but wont
                             * own the der. */
                            nssCrl =
                                CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy,
                                                       SEC_CRL_TYPE,
                                                       CRL_DECODE_DONT_COPY_DER |
                                                       CRL_DECODE_SKIP_ENTRIES);
                            if (!nssCrl) {
                                SECITEM_FreeItem(derCrlCopy, PKIX_TRUE);
                                continue;
                            }
                            /* pkix crl own the der. */
                            PKIX_CHECK(
                                pkix_pl_CRL_CreateWithSignedCRL(nssCrl, 
                                       derCrlCopy, NULL, &crl, plContext),
                                PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
                            /* Left control over memory pointed by derCrlCopy and
                             * nssCrl to pkix crl. */
                            derCrlCopy = NULL;
                            nssCrl = NULL;
                            PKIX_CHECK(PKIX_List_AppendItem
                                       (crlList, (PKIX_PL_Object *) crl, plContext),
                                       PKIX_LISTAPPENDITEMFAILED);
                            PKIX_DECREF(crl);
                            derCrlItem = *attrVal++;
                        }
                        /* Clean up after PKIX_CHECK_ONLY_FATAL */
                        pkixTempErrorReceived = PKIX_FALSE;
                    }
                    sreAttr = *sreAttrArray++;
                }
                PKIX_DECREF(response);
        }

        *pCrls = crlList;
        crlList = NULL;
cleanup:
        if (derCrlCopy) {
            SECITEM_FreeItem(derCrlCopy, PKIX_TRUE);
        }
        if (nssCrl) {
            SEC_DestroyCrl(nssCrl);
        }
        PKIX_DECREF(crl);
        PKIX_DECREF(crlList);
        PKIX_DECREF(response);

        PKIX_RETURN(CERTSTORE);
}
Example #12
0
/* the content of an encrypted data content info is encrypted.
 * it is assumed that for encrypted data, that the data has already
 * been set and is in the "plainContent" field of the content info.
 *
 * cinfo is the content info to encrypt
 *
 * key is the key with which to perform the encryption.  if the
 *     algorithm is a password based encryption algorithm, the
 *     key is actually a password which will be processed per
 *     PKCS #5.
 * 
 * in the event of an error, SECFailure is returned.  SECSuccess
 * indicates a success.
 */
SECStatus 
SEC_PKCS7EncryptContents(PRArenaPool *poolp,
			 SEC_PKCS7ContentInfo *cinfo,
			 SECItem *key,
			 void *wincx)
{
    SECAlgorithmID *algid 	= NULL;
    SECItem *       result 	= NULL;
    SECItem *       src;
    SECItem *       dest;
    SECItem *       blocked_data = NULL;
    void *          mark;
    void *          cx;
    PK11SymKey *    eKey 	= NULL;
    PK11SlotInfo *  slot 	= NULL;

    CK_MECHANISM_TYPE cryptoMechType;
    int             bs;
    SECStatus       rv 		= SECFailure;
    SECItem         *c_param = NULL;

    if((cinfo == NULL) || (key == NULL))
	return SECFailure;

    if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
	return SECFailure;

    algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);	
    if(algid == NULL)
	return SECFailure;

    if(poolp == NULL)
	poolp = cinfo->poolp;

    mark = PORT_ArenaMark(poolp);
    
    src = &cinfo->content.encryptedData->encContentInfo.plainContent;
    dest = &cinfo->content.encryptedData->encContentInfo.encContent;
    dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64));
    dest->len = (src->len + 64);
    if(dest->data == NULL) {
	rv = SECFailure;
	goto loser;
    }

    slot = PK11_GetInternalKeySlot();
    if(slot == NULL) {
	rv = SECFailure;
	goto loser;
    }

    eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
    if(eKey == NULL) {
	rv = SECFailure;
	goto loser;
    }
    
    cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
    if (cryptoMechType == CKM_INVALID_MECHANISM) {
	rv = SECFailure;
	goto loser;
    }

    /* block according to PKCS 8 */
    bs = PK11_GetBlockSize(cryptoMechType, c_param);
    rv = SECSuccess;
    if(bs) {
	char pad_char;
	pad_char = (char)(bs - (src->len % bs));
	if(src->len % bs) {
	    rv = SECSuccess;
	    blocked_data = PK11_BlockData(src, bs);
	    if(blocked_data) {
		PORT_Memset((blocked_data->data + blocked_data->len 
			    - (int)pad_char), 
			    pad_char, (int)pad_char);
	    } else {
		rv = SECFailure;
		goto loser;
	    }
	} else {
	    blocked_data = SECITEM_DupItem(src);
	    if(blocked_data) {
		blocked_data->data = (unsigned char*)PORT_Realloc(
						  blocked_data->data,
						  blocked_data->len + bs);
		if(blocked_data->data) {
		    blocked_data->len += bs;
		    PORT_Memset((blocked_data->data + src->len), (char)bs, bs);
		} else {
		    rv = SECFailure;
		    goto loser;
		}
	    } else {
		rv = SECFailure;
		goto loser;
	    }
	 }
    } else {
	blocked_data = SECITEM_DupItem(src);
	if(!blocked_data) {
	    rv = SECFailure;
	    goto loser;
	}
    }

    cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
		    		    eKey, c_param);
    if(cx == NULL) {
	rv = SECFailure;
	goto loser;
    }

    rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), 
		       (int)(src->len + 64), blocked_data->data, 
		       (int)blocked_data->len);
    PK11_DestroyContext((PK11Context*)cx, PR_TRUE);

loser:
    /* let success fall through */
    if(blocked_data != NULL)
	SECITEM_ZfreeItem(blocked_data, PR_TRUE);

    if(result != NULL)
	SECITEM_ZfreeItem(result, PR_TRUE);

    if(rv == SECFailure)
	PORT_ArenaRelease(poolp, mark);
    else 
	PORT_ArenaUnmark(poolp, mark);

    if(eKey != NULL)
	PK11_FreeSymKey(eKey);

    if(slot != NULL)
	PK11_FreeSlot(slot);

    if(c_param != NULL) 
	SECITEM_ZfreeItem(c_param, PR_TRUE);
	
    return rv;
}
Example #13
0
static SECItem *
crmf_copy_control_value(CRMFControl *inControl)
{
    return SECITEM_DupItem(&inControl->derValue);
}
/*
 * FUNCTION: pkix_pl_GeneralName_Create
 * DESCRIPTION:
 *
 *  Creates new GeneralName which represents the CERTGeneralName pointed to by
 *  "nssAltName" and stores it at "pGenName".
 *
 * PARAMETERS:
 *  "nssAltName"
 *      Address of CERTGeneralName. Must be non-NULL.
 *  "pGenName"
 *      Address where object pointer will be stored. Must be non-NULL.
 *  "plContext" - Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a GeneralName Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */
PKIX_Error *
pkix_pl_GeneralName_Create(
        CERTGeneralName *nssAltName,
        PKIX_PL_GeneralName **pGenName,
        void *plContext)
{
        PKIX_PL_GeneralName *genName = NULL;
        PKIX_PL_X500Name *pkixDN = NULL;
        PKIX_PL_OID *pkixOID = NULL;
        OtherName *otherName = NULL;
        CERTGeneralNameList *nssGenNameList = NULL;
        CERTGeneralNameType nameType;

        PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Create");
        PKIX_NULLCHECK_TWO(nssAltName, pGenName);

        /* create a PKIX_PL_GeneralName object */
        PKIX_CHECK(PKIX_PL_Object_Alloc
                    (PKIX_GENERALNAME_TYPE,
                    sizeof (PKIX_PL_GeneralName),
                    (PKIX_PL_Object **)&genName,
                    plContext),
                    PKIX_COULDNOTCREATEOBJECT);

        nameType = nssAltName->type;

        /*
         * We use CERT_CreateGeneralNameList to create just one CERTGeneralName
         * item for memory allocation reason. If we want to just create one
         * item, we have to use the calling path CERT_NewGeneralName, then
         * CERT_CopyOneGeneralName. With this calling path, if we pass
         * the arena argument as NULL, in CERT_CopyOneGeneralName's subsequent
         * call to CERT_CopyName, it assumes arena should be valid, hence
         * segmentation error (not sure this is a NSS bug, certainly it is
         * not consistent). But on the other hand, we don't want to keep an
         * arena record here explicitely for every PKIX_PL_GeneralName.
         * So I concluded it is better to use CERT_CreateGeneralNameList,
         * which keeps an arena pointer in its data structure and also masks
         * out details calls from this libpkix level.
         */

        PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
        nssGenNameList = CERT_CreateGeneralNameList(nssAltName);

        if (nssGenNameList == NULL) {
                PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
        }

        genName->nssGeneralNameList = nssGenNameList;

        /* initialize fields */
        genName->type = nameType;
        genName->directoryName = NULL;
        genName->OthName = NULL;
        genName->other = NULL;
        genName->oid = NULL;

        switch (nameType){
        case certOtherName:

                PKIX_CHECK(pkix_pl_OtherName_Create
                            (nssAltName, &otherName, plContext),
                            PKIX_OTHERNAMECREATEFAILED);

                genName->OthName = otherName;
                break;

        case certDirectoryName:

                PKIX_CHECK(pkix_pl_DirectoryName_Create
                            (nssAltName, &pkixDN, plContext),
                            PKIX_DIRECTORYNAMECREATEFAILED);

                genName->directoryName = pkixDN;
                break;
        case certRegisterID:
                PKIX_CHECK(PKIX_PL_OID_CreateBySECItem(&nssAltName->name.other,
                                                       &pkixOID, plContext),
                            PKIX_OIDCREATEFAILED);

                genName->oid = pkixOID;
                break;
        case certDNSName:
        case certEDIPartyName:
        case certIPAddress:
        case certRFC822Name:
        case certX400Address:
        case certURI:
                genName->other = SECITEM_DupItem(&nssAltName->name.other);
                if (!genName->other) {
                    PKIX_ERROR(PKIX_OUTOFMEMORY);
                }     
                break;
        default:
                PKIX_ERROR(PKIX_NAMETYPENOTSUPPORTED);
        }

        *pGenName = genName;
        genName = NULL;

cleanup:
        PKIX_DECREF(genName);

        PKIX_RETURN(GENERALNAME);
}