예제 #1
0
CERTUserNotice *
CERT_DecodeUserNotice(SECItem *noticeItem)
{
    PLArenaPool *arena = NULL;
    SECStatus rv;
    CERTUserNotice *userNotice;
    SECItem newNoticeItem;
    
    /* make a new arena */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    
    if ( !arena ) {
	goto loser;
    }

    /* allocate the userNotice structure */
    userNotice = (CERTUserNotice *)PORT_ArenaZAlloc(arena,
						    sizeof(CERTUserNotice));
    
    if ( userNotice == NULL ) {
	goto loser;
    }
    
    userNotice->arena = arena;

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newNoticeItem, noticeItem);
    if ( rv != SECSuccess ) {
	goto loser;
    }

    /* decode the user notice */
    rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate, 
			    &newNoticeItem);

    if ( rv != SECSuccess ) {
	goto loser;
    }

    if (userNotice->derNoticeReference.data != NULL) {

        rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference,
                                    CERT_NoticeReferenceTemplate,
                                    &userNotice->derNoticeReference);
        if (rv == SECFailure) {
            goto loser;
    	}
    }

    return(userNotice);
    
loser:
    if ( arena != NULL ) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    
    return(NULL);
}
예제 #2
0
/* What the hell?
 * https://mxr.mozilla.org/security/source/security/nss/lib/cryptohi/seckey.c#1346 */
SECKEYPublicKey *my_SECKEY_DecodeDERPublicKey (SECItem *pubkder) {
  PRArenaPool *arena;
  SECKEYPublicKey *pubk;
  SECStatus rv;
  SECItem newPubkder;

  arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  if (arena == NULL) {
    return NULL;
  }

  pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
  if (pubk != NULL) {
    pubk->arena = arena;
    pubk->pkcs11Slot = NULL;
    pubk->pkcs11ID = 0;
    pubk->u.rsa.modulus.type = siUnsignedInteger;
    pubk->u.rsa.publicExponent.type = siUnsignedInteger;
    /* copy the DER into the arena, since Quick DER returns data that points
    into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newPubkder, pubkder);
    if ( rv == SECSuccess ) {
      rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate,&newPubkder);
    }

    if (rv == SECSuccess)
      return pubk;
    //SECKEY_DestroyPublicKey (pubk);
  }

  PORT_FreeArena (arena, PR_FALSE);
  return NULL;
}
예제 #3
0
SECStatus CERT_DecodeInhibitAnyExtension
        (CERTCertificateInhibitAny *decodedValue, SECItem *encodedValue)
{
    CERTCertificateInhibitAny decodeContext;
    PLArenaPool *arena = NULL;
    SECStatus rv = SECSuccess;

    /* make a new arena */
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    if ( !arena ) {
        return SECFailure;
    }

    do {

        /* decode the policy mappings */
        decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger;
        rv = SEC_QuickDERDecodeItem(arena,
                &decodeContext, CERT_InhibitAnyTemplate, encodedValue);

        if ( rv != SECSuccess ) {
            break;
        }

        *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data =
                DER_GetInteger(&decodeContext.inhibitAnySkipCerts);

    } while (0);

    PORT_FreeArena(arena, PR_FALSE);
    return(rv);
}
예제 #4
0
SECStatus CERT_FindCRLNumberExten (PRArenaPool *arena, CERTCrl *crl,
                                   SECItem *value)
{
    SECItem encodedExtenValue;
    SECItem *tmpItem = NULL;
    SECStatus rv;
    void *mark = NULL;

    encodedExtenValue.data = NULL;
    encodedExtenValue.len = 0;

    rv = cert_FindExtension(crl->extensions, SEC_OID_X509_CRL_NUMBER,
			  &encodedExtenValue);
    if ( rv != SECSuccess )
	return (rv);

    mark = PORT_ArenaMark(arena);

    tmpItem = SECITEM_ArenaDupItem(arena, &encodedExtenValue);
    if (tmpItem) {
        rv = SEC_QuickDERDecodeItem (arena, value,
                                     SEC_ASN1_GET(SEC_IntegerTemplate),
                                     tmpItem);
    } else {
        rv = SECFailure;
    }

    PORT_Free (encodedExtenValue.data);
    if (rv == SECFailure) {
        PORT_ArenaRelease(arena, mark);
    } else {
        PORT_ArenaUnmark(arena, mark);
    }
    return (rv);
}
예제 #5
0
CERTPrivKeyUsagePeriod *
CERT_DecodePrivKeyUsagePeriodExtension(PLArenaPool *arena, SECItem *extnValue)
{
    SECStatus rv;
    CERTPrivKeyUsagePeriod *pPeriod;
    SECItem newExtnValue;

    /* allocate the certificate policies structure */
    pPeriod = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod);
    if ( pPeriod == NULL ) {
	goto loser;
    }
    
    pPeriod->arena = arena;

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
    if ( rv != SECSuccess ) {
	goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, pPeriod, 
                                CERTPrivateKeyUsagePeriodTemplate,
			        &newExtnValue);
    if ( rv != SECSuccess ) {
	goto loser;
    }
    return pPeriod;
    
loser:
    return NULL;
}
예제 #6
0
/*
 * NSS_SMIMEUtil_GetCertFromEncryptionKeyPreference -
 *				find cert marked by EncryptionKeyPreference attribute
 *
 * "certdb" - handle for the cert database to look in
 * "DERekp" - DER-encoded value of S/MIME Encryption Key Preference attribute
 *
 * if certificate is supposed to be found among the message's included certificates,
 * they are assumed to have been imported already.
 */
CERTCertificate *
NSS_SMIMEUtil_GetCertFromEncryptionKeyPreference(CERTCertDBHandle *certdb, SECItem *DERekp)
{
    PLArenaPool *tmppoolp = NULL;
    CERTCertificate *cert = NULL;
    NSSSMIMEEncryptionKeyPreference ekp;

    tmppoolp = PORT_NewArena(1024);
    if (tmppoolp == NULL)
	return NULL;

    /* decode DERekp */
    if (SEC_QuickDERDecodeItem(tmppoolp, &ekp, smime_encryptionkeypref_template,
                               DERekp) != SECSuccess)
	goto loser;

    /* find cert */
    switch (ekp.selector) {
    case NSSSMIMEEncryptionKeyPref_IssuerSN:
	cert = CERT_FindCertByIssuerAndSN(certdb, ekp.id.issuerAndSN);
	break;
    case NSSSMIMEEncryptionKeyPref_RKeyID:
    case NSSSMIMEEncryptionKeyPref_SubjectKeyID:
	/* XXX not supported yet - we need to be able to look up certs by SubjectKeyID */
	break;
    default:
	PORT_Assert(0);
    }
loser:
    if (tmppoolp) PORT_FreeArena(tmppoolp, PR_FALSE);

    return cert;
}
예제 #7
0
CERTGeneralName *
CERT_DecodeAltNameExtension(PRArenaPool *reqArena, SECItem *EncodedAltName)
{
    SECStatus                  rv = SECSuccess;
    CERTAltNameEncodedContext  encodedContext;
    SECItem*                   newEncodedAltName;

    if (!reqArena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    newEncodedAltName = SECITEM_ArenaDupItem(reqArena, EncodedAltName);
    if (!newEncodedAltName) {
        return NULL;
    }

    encodedContext.encodedGenName = NULL;
    PORT_Memset(&encodedContext, 0, sizeof(CERTAltNameEncodedContext));
    rv = SEC_QuickDERDecodeItem (reqArena, &encodedContext,
                                 CERT_GeneralNamesTemplate, newEncodedAltName);
    if (rv == SECFailure) {
	goto loser;
    }
    if (encodedContext.encodedGenName && encodedContext.encodedGenName[0])
	return cert_DecodeGeneralNames(reqArena,
                                       encodedContext.encodedGenName);
    /* Extension contained an empty GeneralNames sequence */
    /* Treat as extension not found */
    PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
loser:
    return NULL;
}
예제 #8
0
파일: secdig.c 프로젝트: louisshih/jxcore
SGNDigestInfo *
SGN_DecodeDigestInfo(SECItem *didata)
{
    PLArenaPool *arena;
    SGNDigestInfo *di;
    SECStatus rv = SECFailure;
    SECItem      diCopy   = {siBuffer, NULL, 0};

    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    if(arena == NULL)
        return NULL;

    rv = SECITEM_CopyItem(arena, &diCopy, didata);
    if (rv != SECSuccess) {
        PORT_FreeArena(arena, PR_FALSE);
        return NULL;
    }

    di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
    if (di != NULL) {
        di->arena = arena;
        rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy);
    }

    if ((di == NULL) || (rv != SECSuccess)) {
        PORT_FreeArena(arena, PR_FALSE);
        di = NULL;
    }

    return di;
}
예제 #9
0
/*
 * get the value of the X.509 v3 Key Usage Extension
 */
SECStatus
CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem)
{

    SECStatus rv;
    SECItem encodedValue = {siBuffer, NULL, 0 };
    SECItem decodedValue = {siBuffer, NULL, 0 };

    rv = cert_FindExtension
	 (cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID, &encodedValue);
    if (rv == SECSuccess) {
	PLArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
	if (tmpArena) {
	    rv = SEC_QuickDERDecodeItem(tmpArena, &decodedValue, 
	                                SEC_ASN1_GET(SEC_OctetStringTemplate), 
					&encodedValue);
	    if (rv == SECSuccess) {
	        rv = SECITEM_CopyItem(NULL, retItem, &decodedValue);
	    }
	    PORT_FreeArena(tmpArena, PR_FALSE);
	} else {
	    rv = SECFailure;
	}
    }
    SECITEM_FreeItem(&encodedValue, PR_FALSE);
    return rv;
}
예제 #10
0
// 4.2.1.3. Key Usage (id-ce-keyUsage)
// Modeled after GetKeyUsage in certdb.c
Result
CheckKeyUsage(EndEntityOrCA endEntityOrCA,
              bool isTrustAnchor,
              const SECItem* encodedKeyUsage,
              KeyUsages requiredKeyUsagesIfPresent,
              PLArenaPool* arena)
{
  if (!encodedKeyUsage) {
    // TODO: Reject certificates that are being used to verify certificate
    // signatures unless the certificate is a trust anchor, to reduce the
    // chances of an end-entity certificate being abused as a CA certificate.
    // if (endEntityOrCA == MustBeCA && !isTrustAnchor) {
    //   return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
    // }
    //
    // TODO: Users may configure arbitrary certificates as trust anchors, not
    // just roots. We should only allow a certificate without a key usage to be
    // used as a CA when it is self-issued and self-signed.
    return Success;
  }

  SECItem tmpItem;
  Result rv = MapSECStatus(SEC_QuickDERDecodeItem(arena, &tmpItem,
                              SEC_ASN1_GET(SEC_BitStringTemplate),
                              encodedKeyUsage));
  if (rv != Success) {
    return rv;
  }

  // TODO XXX: Why is tmpItem.len > 1?

  KeyUsages allowedKeyUsages = tmpItem.data[0];
  if ((allowedKeyUsages & requiredKeyUsagesIfPresent)
        != requiredKeyUsagesIfPresent) {
    return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
  }

  if (endEntityOrCA == MustBeCA) {
   // "If the keyUsage extension is present, then the subject public key
   //  MUST NOT be used to verify signatures on certificates or CRLs unless
   //  the corresponding keyCertSign or cRLSign bit is set."
   if ((allowedKeyUsages & KU_KEY_CERT_SIGN) == 0) {
      return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
    }
  } else {
    // "The keyCertSign bit is asserted when the subject public key is
    //  used for verifying signatures on public key certificates.  If the
    //  keyCertSign bit is asserted, then the cA bit in the basic
    //  constraints extension (Section 4.2.1.9) MUST also be asserted."
    // TODO XXX: commented out to match classic NSS behavior.
    //if ((allowedKeyUsages & KU_KEY_CERT_SIGN) != 0) {
    //  // XXX: better error code.
    //  return Fail(RecoverableError, SEC_ERROR_INADEQUATE_CERT_TYPE);
    //}
  }

  return Success;
}
예제 #11
0
SECStatus
CERT_DecodePolicyConstraintsExtension
                             (CERTCertificatePolicyConstraints *decodedValue,
                              const SECItem *encodedValue)
{
    CERTCertificatePolicyConstraints decodeContext;
    PLArenaPool *arena = NULL;
    SECStatus rv = SECSuccess;

    /* initialize so we can tell when an optional component is omitted */
    PORT_Memset(&decodeContext, 0, sizeof(decodeContext));

    /* make a new arena */
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    if (!arena) {
        return SECFailure;
    }

    do {
        /* decode the policy constraints */
        rv = SEC_QuickDERDecodeItem(arena,
                &decodeContext, CERT_PolicyConstraintsTemplate, encodedValue);

        if ( rv != SECSuccess ) {
            break;
        }

        if (decodeContext.explicitPolicySkipCerts.len == 0) {
            *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = -1;
        } else {
            *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data =
                    DER_GetInteger(&decodeContext.explicitPolicySkipCerts);
        }

        if (decodeContext.inhibitMappingSkipCerts.len == 0) {
            *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1;
        } else {
            *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data =
                    DER_GetInteger(&decodeContext.inhibitMappingSkipCerts);
        }

        if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data ==
                PR_INT32_MIN) ||
            (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data ==
                PR_INT32_MAX) ||
            (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data ==
                PR_INT32_MIN) ||
            (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data ==
                PR_INT32_MAX)) {
            rv = SECFailure;
        }
    
    } while (0);

    PORT_FreeArena(arena, PR_FALSE);
    return(rv);
}
예제 #12
0
SECStatus CERT_DecodeBasicConstraintValue
   (CERTBasicConstraints *value, SECItem *encodedValue)
{
    EncodedContext decodeContext;
    PRArenaPool *our_pool;
    SECStatus rv = SECSuccess;

    do {
	PORT_Memset (&decodeContext, 0, sizeof (decodeContext));
	/* initialize the value just in case we got "0x30 00", or when the
	   pathLenConstraint is omitted.
         */
	decodeContext.isCA.data =&hexFalse;
	decodeContext.isCA.len = 1;
	
	our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
	if (our_pool == NULL) {
	    PORT_SetError (SEC_ERROR_NO_MEMORY);
	    GEN_BREAK (SECFailure);
	}

        rv = SEC_QuickDERDecodeItem
	     (our_pool, &decodeContext, CERTBasicConstraintsTemplate, encodedValue);
	if (rv == SECFailure)
	    break;
	
	value->isCA = decodeContext.isCA.data 
	              ? (PRBool)(decodeContext.isCA.data[0] != 0)
		      : PR_FALSE;
	if (decodeContext.pathLenConstraint.data == NULL) {
	    /* if the pathLenConstraint is not encoded, and the current setting
	      is CA, then the pathLenConstraint should be set to a negative number
	      for unlimited certificate path.
	     */
	    if (value->isCA)
		value->pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
	} else if (value->isCA) {
	    long len = DER_GetInteger (&decodeContext.pathLenConstraint);
	    if (len < 0 || len == LONG_MAX) {
		PORT_SetError (SEC_ERROR_BAD_DER);
		GEN_BREAK (SECFailure);
	    }
	    value->pathLenConstraint = len;
	} else {
	    /* here we get an error where the subject is not a CA, but
	       the pathLenConstraint is set */
	    PORT_SetError (SEC_ERROR_BAD_DER);
	    GEN_BREAK (SECFailure);
	    break;
	}
	 
    } while (0);
    PORT_FreeArena (our_pool, PR_FALSE);
    return (rv);

}
예제 #13
0
/*
 * get the value of a string type extension
 */
char *
CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag)
{
    SECItem wrapperItem, tmpItem = {siBuffer,0};
    SECStatus rv;
    PLArenaPool *arena = NULL;
    char *retstring = NULL;
    
    wrapperItem.data = NULL;
    tmpItem.data = NULL;
    
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    
    if ( ! arena ) {
	goto loser;
    }
    
    rv = cert_FindExtension(cert->extensions, oidtag,
			       &wrapperItem);
    if ( rv != SECSuccess ) {
	goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, &tmpItem,
                            SEC_ASN1_GET(SEC_IA5StringTemplate), &wrapperItem);

    if ( rv != SECSuccess ) {
	goto loser;
    }

    retstring = (char *)PORT_Alloc(tmpItem.len + 1 );
    if ( retstring == NULL ) {
	goto loser;
    }
    
    PORT_Memcpy(retstring, tmpItem.data, tmpItem.len);
    retstring[tmpItem.len] = '\0';

loser:
    if ( arena ) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    
    if ( wrapperItem.data ) {
	PORT_Free(wrapperItem.data);
    }

    return(retstring);
}
예제 #14
0
CERTAuthKeyID *
CERT_DecodeAuthKeyID (PLArenaPool *arena, const SECItem *encodedValue)
{
    CERTAuthKeyID * value = NULL;
    SECStatus       rv    = SECFailure;
    void *          mark;
    SECItem         newEncodedValue;

    PORT_Assert (arena);
   
    do {
	mark = PORT_ArenaMark (arena);
	value = (CERTAuthKeyID*)PORT_ArenaZAlloc (arena, sizeof (*value));
	if (value == NULL)
	    break;
	value->DERAuthCertIssuer = NULL;
        /* copy the DER into the arena, since Quick DER returns data that points
           into the DER input, which may get freed by the caller */
        rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue);
        if ( rv != SECSuccess ) {
	    break;
        }

        rv = SEC_QuickDERDecodeItem
	     (arena, value, CERTAuthKeyIDTemplate, &newEncodedValue);
	if (rv != SECSuccess)
	    break;

        value->authCertIssuer = cert_DecodeGeneralNames (arena, value->DERAuthCertIssuer);
	if (value->authCertIssuer == NULL)
	    break;
	
	/* what if the general name contains other format but not URI ?
	   hl
	 */
	if ((value->authCertSerialNumber.data && !value->authCertIssuer) ||
	    (!value->authCertSerialNumber.data && value->authCertIssuer)){
	    PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID);
	    break;
	}
    } while (0);

    if (rv != SECSuccess) {
	PORT_ArenaRelease (arena, mark);
	return ((CERTAuthKeyID *)NULL);	    
    } 
    PORT_ArenaUnmark(arena, mark);
    return (value);
}
예제 #15
0
CERTOidSequence *
CERT_DecodeOidSequence(const SECItem *seqItem)
{
    PLArenaPool *arena = NULL;
    SECStatus rv;
    CERTOidSequence *oidSeq;
    SECItem newSeqItem;
    
    /* make a new arena */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    
    if ( !arena ) {
	goto loser;
    }

    /* allocate the userNotice structure */
    oidSeq = (CERTOidSequence *)PORT_ArenaZAlloc(arena,
						 sizeof(CERTOidSequence));
    
    if ( oidSeq == NULL ) {
	goto loser;
    }
    
    oidSeq->arena = arena;

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newSeqItem, seqItem);
    if ( rv != SECSuccess ) {
	goto loser;
    }

    /* decode the user notice */
    rv = SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem);

    if ( rv != SECSuccess ) {
	goto loser;
    }

    return(oidSeq);
    
loser:
    if (arena) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return(NULL);
}
예제 #16
0
CERTCertificatePolicyMappings *
CERT_DecodePolicyMappingsExtension(SECItem *extnValue)
{
    PLArenaPool *arena = NULL;
    SECStatus rv;
    CERTCertificatePolicyMappings *mappings;
    SECItem newExtnValue;
    
    /* make a new arena */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if ( !arena ) {
        goto loser;
    }

    /* allocate the policy mappings structure */
    mappings = (CERTCertificatePolicyMappings *)
        PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicyMappings));
    if ( mappings == NULL ) {
        goto loser;
    }
    mappings->arena = arena;

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
    if ( rv != SECSuccess ) {
        goto loser;
    }

    /* decode the policy mappings */
    rv = SEC_QuickDERDecodeItem
        (arena, mappings, CERT_PolicyMappingsTemplate, &newExtnValue);
    if ( rv != SECSuccess ) {
        goto loser;
    }

    return(mappings);
    
loser:
    if ( arena != NULL ) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    
    return(NULL);
}
예제 #17
0
SECStatus CERT_FindCRLEntryReasonExten (CERTCrlEntry *crlEntry,
                                        CERTCRLEntryReasonCode *value)
{
    SECItem wrapperItem = {siBuffer,0};
    SECItem tmpItem = {siBuffer,0};
    SECStatus rv;
    PRArenaPool *arena = NULL;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);   
    if ( ! arena ) {
	return(SECFailure);
    }
    
    rv = cert_FindExtension(crlEntry->extensions, SEC_OID_X509_REASON_CODE, 
                            &wrapperItem);
    if ( rv != SECSuccess ) {
	goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, &tmpItem,
                                SEC_ASN1_GET(SEC_EnumeratedTemplate),
                                &wrapperItem);

    if ( rv != SECSuccess ) {
	goto loser;
    }

    *value = (CERTCRLEntryReasonCode) DER_GetInteger(&tmpItem);

loser:
    if ( arena ) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    
    if ( wrapperItem.data ) {
	PORT_Free(wrapperItem.data);
    }

    return (rv);
}
예제 #18
0
NSSCMSRecipientInfo *
nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, 
			    NSSCMSRecipientIDSelector type,
                            CERTCertificate *cert, 
			    SECKEYPublicKey *pubKey, 
                            SECItem *subjKeyID, 
			    void* pwfn_arg, 
			    SECItem* DERinput)
{
    NSSCMSRecipientInfo *ri;
    void *mark;
    SECOidTag certalgtag;
    SECStatus rv = SECSuccess;
    NSSCMSRecipientEncryptedKey *rek;
    NSSCMSOriginatorIdentifierOrKey *oiok;
    unsigned long version;
    SECItem *dummy;
    PLArenaPool *poolp;
    CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;
    NSSCMSRecipientIdentifier *rid;
    extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[];

    if (!cmsg) {
	/* a CMSMessage wasn't supplied, create a fake one to hold the pwfunc
	 * and a private arena pool */
	cmsg = NSS_CMSMessage_Create(NULL);
        cmsg->pwfn_arg = pwfn_arg;
	/* mark it as a special cms message */
	cmsg->contentInfo.contentTypeTag = (SECOidData *)&fakeContent;
    }

    poolp = cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

    ri = (NSSCMSRecipientInfo *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientInfo));
    if (ri == NULL)
	goto loser;

    ri->cmsg = cmsg;

    if (DERinput) {
        /* decode everything from DER */
        SECItem newinput;
        SECStatus rv = SECITEM_CopyItem(poolp, &newinput, DERinput);
        if (SECSuccess != rv)
            goto loser;
        rv = SEC_QuickDERDecodeItem(poolp, ri, NSSCMSRecipientInfoTemplate, &newinput);
        if (SECSuccess != rv)
            goto loser;
    }

    switch (type) {
        case NSSCMSRecipientID_IssuerSN:
        {
            ri->cert = CERT_DupCertificate(cert);
            if (NULL == ri->cert)
                goto loser;
            spki = &(cert->subjectPublicKeyInfo);
            break;
        }
        
        case NSSCMSRecipientID_SubjectKeyID:
        {
            PORT_Assert(pubKey);
            spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
            break;
        }

	case NSSCMSRecipientID_BrandNew:
	    goto done;
	    break;

        default:
            /* unkown type */
            goto loser;
            break;
    }

    certalgtag = SECOID_GetAlgorithmTag(&(spki->algorithm));

    rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;
    switch (certalgtag) {
    case SEC_OID_PKCS1_RSA_ENCRYPTION:
	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;
	rid->identifierType = type;
	if (type == NSSCMSRecipientID_IssuerSN) {
	    rid->id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);
	    if (rid->id.issuerAndSN == NULL) {
	      break;
	    }
	} else if (type == NSSCMSRecipientID_SubjectKeyID){
	    NSSCMSKeyTransRecipientInfoEx *riExtra;

	    rid->id.subjectKeyID = PORT_ArenaNew(poolp, SECItem);
	    if (rid->id.subjectKeyID == NULL) {
		rv = SECFailure;
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		break;
	    } 
	    SECITEM_CopyItem(poolp, rid->id.subjectKeyID, subjKeyID);
	    if (rid->id.subjectKeyID->data == NULL) {
		rv = SECFailure;
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		break;
	    }
	    riExtra = &ri->ri.keyTransRecipientInfoEx;
	    riExtra->version = 0;
	    riExtra->pubKey = SECKEY_CopyPublicKey(pubKey);
	    if (riExtra->pubKey == NULL) {
		rv = SECFailure;
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		break;
	    }
	} else {
	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
	    rv = SECFailure;
	}
	break;
    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
	PORT_Assert(type == NSSCMSRecipientID_IssuerSN);
	if (type != NSSCMSRecipientID_IssuerSN) {
	    rv = SECFailure;
	    break;
	}
	/* a key agreement op */
	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyAgree;

	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {
	    rv = SECFailure;
	    break;
	}
	/* we do not support the case where multiple recipients 
	 * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys
	 * in this case, we would need to walk all the recipientInfos, take the
	 * ones that do KeyAgreement algorithms and join them, algorithm by algorithm
	 * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */

	/* only epheremal-static Diffie-Hellman is supported for now
	 * this is the only form of key agreement that provides potential anonymity
	 * of the sender, plus we do not have to include certs in the message */

	/* force single recipientEncryptedKey for now */
	if ((rek = NSS_CMSRecipientEncryptedKey_Create(poolp)) == NULL) {
	    rv = SECFailure;
	    break;
	}

	/* hardcoded IssuerSN choice for now */
	rek->recipientIdentifier.identifierType = NSSCMSKeyAgreeRecipientID_IssuerSN;
	if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) {
	    rv = SECFailure;
	    break;
	}

	oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);

	/* see RFC2630 12.3.1.1 */
	oiok->identifierType = NSSCMSOriginatorIDOrKey_OriginatorPublicKey;

	rv = NSS_CMSArray_Add(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys,
				    (void *)rek);

	break;
    default:
	/* other algorithms not supported yet */
	/* NOTE that we do not support any KEK algorithm */
	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
	rv = SECFailure;
	break;
    }

    if (rv == SECFailure)
	goto loser;

    /* set version */
    switch (ri->recipientInfoType) {
    case NSSCMSRecipientInfoID_KeyTrans:
	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType == NSSCMSRecipientID_IssuerSN)
	    version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN;
	else
	    version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY;
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyTransRecipientInfo.version), version);
	if (dummy == NULL)
	    goto loser;
	break;
    case NSSCMSRecipientInfoID_KeyAgree:
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyAgreeRecipientInfo.version),
						NSS_CMS_KEYAGREE_RECIPIENT_INFO_VERSION);
	if (dummy == NULL)
	    goto loser;
	break;
    case NSSCMSRecipientInfoID_KEK:
	/* NOTE: this cannot happen as long as we do not support any KEK algorithm */
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.kekRecipientInfo.version),
						NSS_CMS_KEK_RECIPIENT_INFO_VERSION);
	if (dummy == NULL)
	    goto loser;
	break;
    
    }

done:
    PORT_ArenaUnmark (poolp, mark);
    if (freeSpki)
      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
    return ri;

loser:
    if (ri && ri->cert) {
        CERT_DestroyCertificate(ri->cert);
    }
    if (freeSpki) {
      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
    }
    PORT_ArenaRelease (poolp, mark);
    if (cmsg->contentInfo.contentTypeTag == &fakeContent) {
	NSS_CMSMessage_Destroy(cmsg);
    }
    return NULL;
}
예제 #19
0
static CERTCertificatePolicies *
secu_DecodeCertificatePoliciesExtension(SECItem *extnValue)
{
    PRArenaPool *arena = NULL;
    SECStatus rv;
    CERTCertificatePolicies *policies;
    CERTPolicyInfo **policyInfos, *policyInfo;
    CERTPolicyQualifier **policyQualifiers, *policyQualifier;
    SECItem newExtnValue;
    
    /* make a new arena */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    
    if ( !arena ) {
	goto loser;
    }

    /* allocate the certifiate policies structure */
    policies = PORT_ArenaZNew(arena, CERTCertificatePolicies);
    if ( policies == NULL ) {
	goto loser;
    }
    
    policies->arena = arena;

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
    if ( rv != SECSuccess ) {
	goto loser;
    }

    /* decode the policy info */
    rv = SEC_QuickDERDecodeItem(arena, policies, 
                                secu_CertificatePoliciesTemplate,
			        &newExtnValue);

    if ( rv != SECSuccess ) {
	goto loser;
    }

    /* initialize the oid tags */
    policyInfos = policies->policyInfos;
    while (policyInfos != NULL && *policyInfos != NULL ) {
	policyInfo = *policyInfos;
	policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
	policyQualifiers = policyInfo->policyQualifiers;
	while ( policyQualifiers && *policyQualifiers != NULL ) {
	    policyQualifier = *policyQualifiers;
	    policyQualifier->oid =
		SECOID_FindOIDTag(&policyQualifier->qualifierID);
	    policyQualifiers++;
	}
	policyInfos++;
    }

    return(policies);
    
loser:
    if ( arena != NULL ) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    
    return(NULL);
}
예제 #20
0
SECStatus
PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
                                      SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue,
                                      PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
                                      SECKEYPrivateKey **privk, void *wincx)
{
    SECStatus rv = SECFailure;
    SECKEYRawPrivateKey *lpk = NULL;
    const SEC_ASN1Template *keyTemplate, *paramTemplate;
    void *paramDest = NULL;
    PLArenaPool *arena = NULL;

    arena = PORT_NewArena(2048);
    if (!arena) {
        return SECFailure;
    }

    /* need to change this to use RSA/DSA keys */
    lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena,
                                                  sizeof(SECKEYRawPrivateKey));
    if (lpk == NULL) {
        goto loser;
    }
    lpk->arena = arena;

    switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
            prepare_rsa_priv_key_export_for_asn1(lpk);
            keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
            paramTemplate = NULL;
            paramDest = NULL;
            lpk->keyType = rsaKey;
            break;
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
            prepare_dsa_priv_key_export_for_asn1(lpk);
            keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
            paramTemplate = SECKEY_PQGParamsTemplate;
            paramDest = &(lpk->u.dsa.params);
            lpk->keyType = dsaKey;
            break;
        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
            if (!publicValue) {
                goto loser;
            }
            prepare_dh_priv_key_export_for_asn1(lpk);
            keyTemplate = SECKEY_DHPrivateKeyExportTemplate;
            paramTemplate = NULL;
            paramDest = NULL;
            lpk->keyType = dhKey;
            break;
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
            prepare_ec_priv_key_export_for_asn1(lpk);
            keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
            paramTemplate = NULL;
            paramDest = NULL;
            lpk->keyType = ecKey;
            break;

        default:
            keyTemplate = NULL;
            paramTemplate = NULL;
            paramDest = NULL;
            break;
    }

    if (!keyTemplate) {
        goto loser;
    }

    /* decode the private key and any algorithm parameters */
    rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
    if (rv != SECSuccess) {
        goto loser;
    }

    if (lpk->keyType == ecKey) {
        /* Convert length in bits to length in bytes. */
        lpk->u.ec.publicValue.len >>= 3;

        /* Always override curveOID, we're ignoring any given value. */
        rv = SECITEM_CopyItem(arena, &lpk->u.ec.curveOID,
                              &pki->algorithm.parameters);
        if (rv != SECSuccess) {
            goto loser;
        }
    }
예제 #21
0
/* find a URL extension in the cert or its CA
 * apply the base URL string if it exists
 */
char *
CERT_FindCertURLExtension(CERTCertificate *cert, int tag, int catag)
{
    SECStatus rv;
    SECItem urlitem = {siBuffer,0};
    SECItem baseitem = {siBuffer,0};
    SECItem urlstringitem = {siBuffer,0};
    SECItem basestringitem = {siBuffer,0};
    PRArenaPool *arena = NULL;
    PRBool hasbase;
    char *urlstring;
    char *str;
    int len;
    unsigned int i;
    
    urlstring = NULL;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if ( ! arena ) {
	goto loser;
    }
    
    hasbase = PR_FALSE;
    
    rv = cert_FindExtension(cert->extensions, tag, &urlitem);
    if ( rv == SECSuccess ) {
	rv = cert_FindExtension(cert->extensions, SEC_OID_NS_CERT_EXT_BASE_URL,
				   &baseitem);
	if ( rv == SECSuccess ) {
	    hasbase = PR_TRUE;
	}
	
    } else if ( catag ) {
	/* if the cert doesn't have the extensions, see if the issuer does */
	rv = CERT_FindIssuerCertExtension(cert, catag, &urlitem);
	if ( rv != SECSuccess ) {
	    goto loser;
	}	    
	rv = CERT_FindIssuerCertExtension(cert, SEC_OID_NS_CERT_EXT_BASE_URL,
					 &baseitem);
	if ( rv == SECSuccess ) {
	    hasbase = PR_TRUE;
	}
    } else {
	goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, &urlstringitem,
                                SEC_ASN1_GET(SEC_IA5StringTemplate), &urlitem);

    if ( rv != SECSuccess ) {
	goto loser;
    }
    if ( hasbase ) {
	rv = SEC_QuickDERDecodeItem(arena, &basestringitem,
                                    SEC_ASN1_GET(SEC_IA5StringTemplate),
                                    &baseitem);

	if ( rv != SECSuccess ) {
	    goto loser;
	}
    }
    
    len = urlstringitem.len + ( hasbase ? basestringitem.len : 0 ) + 1;
    
    str = urlstring = (char *)PORT_Alloc(len);
    if ( urlstring == NULL ) {
	goto loser;
    }
    
    /* copy the URL base first */
    if ( hasbase ) {

	/* if the urlstring has a : in it, then we assume it is an absolute
	 * URL, and will not get the base string pre-pended
	 */
	for ( i = 0; i < urlstringitem.len; i++ ) {
	    if ( urlstringitem.data[i] == ':' ) {
		goto nobase;
	    }
	}
	
	PORT_Memcpy(str, basestringitem.data, basestringitem.len);
	str += basestringitem.len;
	
    }

nobase:
    /* copy the rest (or all) of the URL */
    PORT_Memcpy(str, urlstringitem.data, urlstringitem.len);
    str += urlstringitem.len;
    
    *str = '\0';
    goto done;
    
loser:
    if ( urlstring ) {
	PORT_Free(urlstring);
    }
    
    urlstring = NULL;
done:
    if ( arena ) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    if ( baseitem.data ) {
	PORT_Free(baseitem.data);
    }
    if ( urlitem.data ) {
	PORT_Free(urlitem.data);
    }

    return(urlstring);
}
예제 #22
0
/*
 * smime_choose_cipher - choose a cipher that works for all the recipients
 *
 * "scert"  - sender's certificate
 * "rcerts" - recipient's certificates
 */
static long
smime_choose_cipher(CERTCertificate *scert, CERTCertificate **rcerts)
{
    PLArenaPool *poolp;
    long cipher;
    long chosen_cipher;
    int *cipher_abilities;
    int *cipher_votes;
    int weak_mapi;
    int strong_mapi;
    int aes128_mapi;
    int aes256_mapi;
    int rcount, mapi, max, i;

    chosen_cipher = SMIME_RC2_CBC_40;		/* the default, LCD */
    weak_mapi = smime_mapi_by_cipher(chosen_cipher);
    aes128_mapi = smime_mapi_by_cipher(SMIME_AES_CBC_128);
    aes256_mapi = smime_mapi_by_cipher(SMIME_AES_CBC_256);

    poolp = PORT_NewArena (1024);		/* XXX what is right value? */
    if (poolp == NULL)
	goto done;

    cipher_abilities = (int *)PORT_ArenaZAlloc(poolp, smime_cipher_map_count * sizeof(int));
    cipher_votes     = (int *)PORT_ArenaZAlloc(poolp, smime_cipher_map_count * sizeof(int));
    if (cipher_votes == NULL || cipher_abilities == NULL)
	goto done;

    /* Make triple-DES the strong cipher. */
    strong_mapi = smime_mapi_by_cipher (SMIME_DES_EDE3_168);

    /* walk all the recipient's certs */
    for (rcount = 0; rcerts[rcount] != NULL; rcount++) {
	SECItem *profile;
	NSSSMIMECapability **caps;
	int pref;

	/* the first cipher that matches in the user's SMIME profile gets
	 * "smime_cipher_map_count" votes; the next one gets "smime_cipher_map_count" - 1
	 * and so on. If every cipher matches, the last one gets 1 (one) vote */
	pref = smime_cipher_map_count;

	/* find recipient's SMIME profile */
	profile = CERT_FindSMimeProfile(rcerts[rcount]);

	if (profile != NULL && profile->data != NULL && profile->len > 0) {
	    /* we have a profile (still DER-encoded) */
	    caps = NULL;
	    /* decode it */
	    if (SEC_QuickDERDecodeItem(poolp, &caps,
                    NSSSMIMECapabilitiesTemplate, profile) == SECSuccess &&
		    caps != NULL)
	    {
		/* walk the SMIME capabilities for this recipient */
		for (i = 0; caps[i] != NULL; i++) {
		    cipher = nss_SMIME_FindCipherForSMIMECap(caps[i]);
		    mapi = smime_mapi_by_cipher(cipher);
		    if (mapi >= 0) {
			/* found the cipher */
			cipher_abilities[mapi]++;
			cipher_votes[mapi] += pref;
			--pref;
		    }
		}
	    }
	} else {
	    /* no profile found - so we can only assume that the user can do
	     * the mandatory algorithms which are RC2-40 (weak crypto) and
	     * 3DES (strong crypto), unless the user has an elliptic curve
	     * key.  For elliptic curve keys, RFC 5753 mandates support
	     * for AES 128 CBC. */
	    SECKEYPublicKey *key;
	    unsigned int pklen_bits;
	    KeyType key_type;

	    /*
	     * if recipient's public key length is > 512, vote for a strong cipher
	     * please not that the side effect of this is that if only one recipient
	     * has an export-level public key, the strong cipher is disabled.
	     *
	     * XXX This is probably only good for RSA keys.  What I would
	     * really like is a function to just say;  Is the public key in
	     * this cert an export-length key?  Then I would not have to
	     * know things like the value 512, or the kind of key, or what
	     * a subjectPublicKeyInfo is, etc.
	     */
	    key = CERT_ExtractPublicKey(rcerts[rcount]);
	    pklen_bits = 0;
	    key_type = nullKey;
	    if (key != NULL) {
		pklen_bits = SECKEY_PublicKeyStrengthInBits (key);
		key_type = SECKEY_GetPublicKeyType(key);
		SECKEY_DestroyPublicKey (key);
		key = NULL;
	    }

	    if (key_type == ecKey) {
		/* While RFC 5753 mandates support for AES-128 CBC, should use
		 * AES 256 if user's key provides more than 128 bits of
		 * security strength so that symmetric key is not weak link. */

		/* RC2-40 is not compatible with elliptic curve keys. */
		chosen_cipher = SMIME_DES_EDE3_168;
		if (pklen_bits > 256) {
		    cipher_abilities[aes256_mapi]++;
		    cipher_votes[aes256_mapi] += pref;
		    pref--;
		}
		cipher_abilities[aes128_mapi]++;
		cipher_votes[aes128_mapi] += pref;
		pref--;
		cipher_abilities[strong_mapi]++;
		cipher_votes[strong_mapi] += pref;
		pref--;
	    } else {
		if (pklen_bits > 512) {
		    /* cast votes for the strong algorithm */
		    cipher_abilities[strong_mapi]++;
		    cipher_votes[strong_mapi] += pref;
		    pref--;
		}

		/* always cast (possibly less) votes for the weak algorithm */
		cipher_abilities[weak_mapi]++;
		cipher_votes[weak_mapi] += pref;
	    } 
	}
	if (profile != NULL)
	    SECITEM_FreeItem(profile, PR_TRUE);
    }

    /* find cipher that is agreeable by all recipients and that has the most votes */
    max = 0;
    for (mapi = 0; mapi < smime_cipher_map_count; mapi++) {
	/* if not all of the recipients can do this, forget it */
	if (cipher_abilities[mapi] != rcount)
	    continue;
	/* if cipher is not enabled or not allowed by policy, forget it */
	if (!smime_cipher_map[mapi].enabled || !smime_cipher_map[mapi].allowed)
	    continue;
	/* now see if this one has more votes than the last best one */
	if (cipher_votes[mapi] >= max) {
	    /* if equal number of votes, prefer the ones further down in the list */
	    /* with the expectation that these are higher rated ciphers */
	    chosen_cipher = smime_cipher_map[mapi].cipher;
	    max = cipher_votes[mapi];
	}
    }
    /* if no common cipher was found, chosen_cipher stays at the default */

done:
    if (poolp != NULL)
	PORT_FreeArena (poolp, PR_FALSE);

    return chosen_cipher;
}
예제 #23
0
SECStatus
SGN_End(SGNContext *cx, SECItem *result)
{
    unsigned char digest[HASH_LENGTH_MAX];
    unsigned part1;
    int signatureLen;
    SECStatus rv;
    SECItem digder, sigitem;
    PLArenaPool *arena = 0;
    SECKEYPrivateKey *privKey = cx->key;
    SGNDigestInfo *di = 0;

    result->data = 0;
    digder.data = 0;
    sigitem.data = 0;

    /* Finish up digest function */
    if (cx->hashcx == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest));

    if (privKey->keyType == rsaKey &&
        cx->signalg != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {

        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (!arena) {
            rv = SECFailure;
            goto loser;
        }

        /* Construct digest info */
        di = SGN_CreateDigestInfo(cx->hashalg, digest, part1);
        if (!di) {
            rv = SECFailure;
            goto loser;
        }

        /* Der encode the digest as a DigestInfo */
        rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate,
                        di);
        if (rv != SECSuccess) {
            goto loser;
        }
    } else {
        digder.data = digest;
        digder.len = part1;
    }

    /*
    ** Encrypt signature after constructing appropriate PKCS#1 signature
    ** block
    */
    signatureLen = PK11_SignatureLen(privKey);
    if (signatureLen <= 0) {
        PORT_SetError(SEC_ERROR_INVALID_KEY);
        rv = SECFailure;
        goto loser;
    }
    sigitem.len = signatureLen;
    sigitem.data = (unsigned char *)PORT_Alloc(signatureLen);

    if (sigitem.data == NULL) {
        rv = SECFailure;
        goto loser;
    }

    if (cx->signalg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
        CK_RSA_PKCS_PSS_PARAMS mech;
        SECItem mechItem = { siBuffer, (unsigned char *)&mech, sizeof(mech) };

        PORT_Memset(&mech, 0, sizeof(mech));

        if (cx->params && cx->params->data) {
            SECKEYRSAPSSParams params;

            arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
            if (!arena) {
                rv = SECFailure;
                goto loser;
            }

            PORT_Memset(&params, 0, sizeof(params));
            rv = SEC_QuickDERDecodeItem(arena, &params,
                                        SECKEY_RSAPSSParamsTemplate,
                                        cx->params);
            if (rv != SECSuccess) {
                goto loser;
            }
            rv = sec_RSAPSSParamsToMechanism(&mech, &params);
            if (rv != SECSuccess) {
                goto loser;
            }
        } else {
            mech.hashAlg = CKM_SHA_1;
            mech.mgf = CKG_MGF1_SHA1;
            mech.sLen = digder.len;
        }
        rv = PK11_SignWithMechanism(privKey, CKM_RSA_PKCS_PSS, &mechItem,
                                    &sigitem, &digder);
        if (rv != SECSuccess) {
            goto loser;
        }
    } else {
        rv = PK11_Sign(privKey, &sigitem, &digder);
        if (rv != SECSuccess) {
            goto loser;
        }
    }

    if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) ||
        (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
        /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */
        rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len);
        if (rv != SECSuccess)
            goto loser;
        SECITEM_FreeItem(&sigitem, PR_FALSE);
    } else {
        result->len = sigitem.len;
        result->data = sigitem.data;
    }

loser:
    if (rv != SECSuccess) {
        SECITEM_FreeItem(&sigitem, PR_FALSE);
    }
    SGN_DestroyDigestInfo(di);
    if (arena != NULL) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return rv;
}
예제 #24
0
static SECItem *
sec_CreateRSAPSSParameters(PLArenaPool *arena,
                           SECItem *result,
                           SECOidTag hashAlgTag,
                           const SECItem *params,
                           const SECKEYPrivateKey *key)
{
    SECKEYRSAPSSParams pssParams;
    int modBytes, hashLength;
    unsigned long saltLength;
    PRBool defaultSHA1 = PR_FALSE;
    SECStatus rv;

    if (key->keyType != rsaKey && key->keyType != rsaPssKey) {
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
        return NULL;
    }

    PORT_Memset(&pssParams, 0, sizeof(pssParams));

    if (params && params->data) {
        /* The parameters field should either be empty or contain
         * valid RSA-PSS parameters */
        PORT_Assert(!(params->len == 2 &&
                      params->data[0] == SEC_ASN1_NULL &&
                      params->data[1] == 0));
        rv = SEC_QuickDERDecodeItem(arena, &pssParams,
                                    SECKEY_RSAPSSParamsTemplate,
                                    params);
        if (rv != SECSuccess) {
            return NULL;
        }
        defaultSHA1 = PR_TRUE;
    }

    if (pssParams.trailerField.data) {
        unsigned long trailerField;

        rv = SEC_ASN1DecodeInteger((SECItem *)&pssParams.trailerField,
                                   &trailerField);
        if (rv != SECSuccess) {
            return NULL;
        }
        if (trailerField != 1) {
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return NULL;
        }
    }

    modBytes = PK11_GetPrivateModulusLen((SECKEYPrivateKey *)key);

    /* Determine the hash algorithm to use, based on hashAlgTag and
     * pssParams.hashAlg; there are four cases */
    if (hashAlgTag != SEC_OID_UNKNOWN) {
        SECOidTag tag = SEC_OID_UNKNOWN;

        if (pssParams.hashAlg) {
            tag = SECOID_GetAlgorithmTag(pssParams.hashAlg);
        } else if (defaultSHA1) {
            tag = SEC_OID_SHA1;
        }

        if (tag != SEC_OID_UNKNOWN && tag != hashAlgTag) {
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return NULL;
        }
    } else if (hashAlgTag == SEC_OID_UNKNOWN) {
        if (pssParams.hashAlg) {
            hashAlgTag = SECOID_GetAlgorithmTag(pssParams.hashAlg);
        } else if (defaultSHA1) {
            hashAlgTag = SEC_OID_SHA1;
        } else {
            /* Find a suitable hash algorithm based on the NIST recommendation */
            if (modBytes <= 384) { /* 128, in NIST 800-57, Part 1 */
                hashAlgTag = SEC_OID_SHA256;
            } else if (modBytes <= 960) { /* 192, NIST 800-57, Part 1 */
                hashAlgTag = SEC_OID_SHA384;
            } else {
                hashAlgTag = SEC_OID_SHA512;
            }
        }
    }

    if (hashAlgTag != SEC_OID_SHA1 && hashAlgTag != SEC_OID_SHA224 &&
        hashAlgTag != SEC_OID_SHA256 && hashAlgTag != SEC_OID_SHA384 &&
        hashAlgTag != SEC_OID_SHA512) {
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
        return NULL;
    }

    /* Now that the hash algorithm is decided, check if it matches the
     * existing parameters if any */
    if (pssParams.maskAlg) {
        SECAlgorithmID maskHashAlg;

        if (SECOID_GetAlgorithmTag(pssParams.maskAlg) != SEC_OID_PKCS1_MGF1) {
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
            return NULL;
        }

        if (pssParams.maskAlg->parameters.data == NULL) {
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
            return NULL;
        }

        PORT_Memset(&maskHashAlg, 0, sizeof(maskHashAlg));
        rv = SEC_QuickDERDecodeItem(arena, &maskHashAlg,
                                    SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
                                    &pssParams.maskAlg->parameters);
        if (rv != SECSuccess) {
            return NULL;
        }

        /* Following the recommendation in RFC 4055, assume the hash
         * algorithm identical to pssParam.hashAlg */
        if (SECOID_GetAlgorithmTag(&maskHashAlg) != hashAlgTag) {
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
            return NULL;
        }
    } else if (defaultSHA1) {
        if (hashAlgTag != SEC_OID_SHA1) {
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
            return NULL;
        }
    }

    hashLength = HASH_ResultLenByOidTag(hashAlgTag);

    if (pssParams.saltLength.data) {
        rv = SEC_ASN1DecodeInteger((SECItem *)&pssParams.saltLength,
                                   &saltLength);
        if (rv != SECSuccess) {
            return NULL;
        }

        /* The specified salt length is too long */
        if (saltLength > modBytes - hashLength - 2) {
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return NULL;
        }
    } else if (defaultSHA1) {
        saltLength = 20;
    }

    /* Fill in the parameters */
    if (pssParams.hashAlg) {
        if (hashAlgTag == SEC_OID_SHA1) {
            /* Omit hashAlg if the the algorithm is SHA-1 (default) */
            pssParams.hashAlg = NULL;
        }
    } else {
        if (hashAlgTag != SEC_OID_SHA1) {
            pssParams.hashAlg = PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
            if (!pssParams.hashAlg) {
                return NULL;
            }
            rv = SECOID_SetAlgorithmID(arena, pssParams.hashAlg, hashAlgTag,
                                       NULL);
            if (rv != SECSuccess) {
                return NULL;
            }
        }
    }

    if (pssParams.maskAlg) {
        if (hashAlgTag == SEC_OID_SHA1) {
            /* Omit maskAlg if the the algorithm is SHA-1 (default) */
            pssParams.maskAlg = NULL;
        }
    } else {
        if (hashAlgTag != SEC_OID_SHA1) {
            SECItem *hashAlgItem;

            PORT_Assert(pssParams.hashAlg != NULL);

            hashAlgItem = SEC_ASN1EncodeItem(arena, NULL, pssParams.hashAlg,
                                             SEC_ASN1_GET(SECOID_AlgorithmIDTemplate));
            if (!hashAlgItem) {
                return NULL;
            }
            pssParams.maskAlg = PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
            if (!pssParams.maskAlg) {
                return NULL;
            }
            rv = SECOID_SetAlgorithmID(arena, pssParams.maskAlg,
                                       SEC_OID_PKCS1_MGF1, hashAlgItem);
            if (rv != SECSuccess) {
                return NULL;
            }
        }
    }

    if (pssParams.saltLength.data) {
        if (saltLength == 20) {
            /* Omit the salt length if it is the default */
            pssParams.saltLength.data = NULL;
        }
    } else {
        /* Find a suitable length from the hash algorithm and modulus bits */
        saltLength = PR_MIN(hashLength, modBytes - hashLength - 2);

        if (saltLength != 20 &&
            !SEC_ASN1EncodeInteger(arena, &pssParams.saltLength, saltLength)) {
            return NULL;
        }
    }

    if (pssParams.trailerField.data) {
        /* Omit trailerField if the value is 1 (default) */
        pssParams.trailerField.data = NULL;
    }

    return SEC_ASN1EncodeItem(arena, result,
                              &pssParams, SECKEY_RSAPSSParamsTemplate);
}
NS_IMETHODIMP
nsDataSignatureVerifier::VerifyData(const nsACString & aData,
                                    const nsACString & aSignature,
                                    const nsACString & aPublicKey,
                                    bool *_retval)
{
    // Allocate an arena to handle the majority of the allocations
    PRArenaPool *arena;
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena)
        return NS_ERROR_OUT_OF_MEMORY;

    // Base 64 decode the key
    SECItem keyItem;
    PORT_Memset(&keyItem, 0, sizeof(SECItem));
    if (!NSSBase64_DecodeBuffer(arena, &keyItem,
                                nsPromiseFlatCString(aPublicKey).get(),
                                aPublicKey.Length())) {
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    
    // Extract the public key from the data
    CERTSubjectPublicKeyInfo *pki = SECKEY_DecodeDERSubjectPublicKeyInfo(&keyItem);
    if (!pki) {
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    SECKEYPublicKey *publicKey = SECKEY_ExtractPublicKey(pki);
    SECKEY_DestroySubjectPublicKeyInfo(pki);
    pki = nullptr;
    
    if (!publicKey) {
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    
    // Base 64 decode the signature
    SECItem signatureItem;
    PORT_Memset(&signatureItem, 0, sizeof(SECItem));
    if (!NSSBase64_DecodeBuffer(arena, &signatureItem,
                                nsPromiseFlatCString(aSignature).get(),
                                aSignature.Length())) {
        SECKEY_DestroyPublicKey(publicKey);
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    
    // Decode the signature and algorithm
    CERTSignedData sigData;
    PORT_Memset(&sigData, 0, sizeof(CERTSignedData));
    SECStatus ss = SEC_QuickDERDecodeItem(arena, &sigData, 
                                          CERT_SignatureDataTemplate,
                                          &signatureItem);
    if (ss != SECSuccess) {
        SECKEY_DestroyPublicKey(publicKey);
        PORT_FreeArena(arena, false);
        return NS_ERROR_FAILURE;
    }
    
    // Perform the final verification
    DER_ConvertBitString(&(sigData.signature));
    ss = VFY_VerifyDataWithAlgorithmID((const unsigned char*)nsPromiseFlatCString(aData).get(),
                                       aData.Length(), publicKey,
                                       &(sigData.signature),
                                       &(sigData.signatureAlgorithm),
                                       NULL, NULL);
    
    // Clean up remaining objects
    SECKEY_DestroyPublicKey(publicKey);
    PORT_FreeArena(arena, false);
    
    *_retval = (ss == SECSuccess);

    return NS_OK;
}
예제 #26
0
CERTCrlDistributionPoints *
CERT_DecodeCRLDistributionPoints (PLArenaPool *arena, SECItem *encodedValue)
{
   CERTCrlDistributionPoints *value = NULL;    
   CRLDistributionPoint **pointList, *point;    
   SECStatus rv = SECSuccess;
   SECItem newEncodedValue;

   PORT_Assert (arena);
   do {
	value = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
	if (value == NULL) {
	    rv = SECFailure;
	    break;
	}

        /* copy the DER into the arena, since Quick DER returns data that points
           into the DER input, which may get freed by the caller */
        rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue);
        if (rv != SECSuccess)
	    break;

	rv = SEC_QuickDERDecodeItem(arena, &value->distPoints, 
		CERTCRLDistributionPointsTemplate, &newEncodedValue);
	if (rv != SECSuccess)
	    break;

	pointList = value->distPoints;
	while (NULL != (point = *pointList)) {

	    /* get the data if the distributionPointName is not omitted */
	    if (point->derDistPoint.data != NULL) {
		rv = SEC_QuickDERDecodeItem(arena, point, 
			DistributionPointNameTemplate, &(point->derDistPoint));
		if (rv != SECSuccess)
		    break;

		switch (point->distPointType) {
		case generalName:
		    point->distPoint.fullName = 
			cert_DecodeGeneralNames(arena, point->derFullName);
		    rv = point->distPoint.fullName ? SECSuccess : SECFailure;
		    break;

		case relativeDistinguishedName:
		    break;

		default:
		    PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID);
		    rv = SECFailure;
		    break;
		} /* end switch */
		if (rv != SECSuccess)
		    break;
	    } /* end if */

	    /* Get the reason code if it's not omitted in the encoding */
	    if (point->bitsmap.data != NULL) {
	    	SECItem bitsmap = point->bitsmap;
		DER_ConvertBitString(&bitsmap);
		rv = SECITEM_CopyItem(arena, &point->reasons, &bitsmap);
		if (rv != SECSuccess)
		    break;
	    }

	    /* Get the crl issuer name if it's not omitted in the encoding */
	    if (point->derCrlIssuer != NULL) {
		point->crlIssuer = cert_DecodeGeneralNames(arena, 
			           point->derCrlIssuer);
		if (!point->crlIssuer)
		    break;
	    }
	    ++pointList;
	} /* end while points remain */
   } while (0);
   return (rv == SECSuccess ? value : NULL);
}
예제 #27
0
/*
 * check the consistancy and initialize a Public Key Object
 */
static CK_RV
lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
                         CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
{
    CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE;
    CK_RV crv = CKR_OK;
    NSSLOWKEYPrivateKey *priv;
    SECItem pubKeySpace = { siBuffer, NULL, 0 };
    SECItem *pubKey;
#ifndef NSS_DISABLE_ECC
    SECItem pubKey2Space = { siBuffer, NULL, 0 };
    PLArenaPool *arena = NULL;
#endif /* NSS_DISABLE_ECC */
    NSSLOWKEYDBHandle *keyHandle = NULL;

    switch (key_type) {
        case CKK_RSA:
            pubKeyAttr = CKA_MODULUS;
            break;
#ifndef NSS_DISABLE_ECC
        case CKK_EC:
            pubKeyAttr = CKA_EC_POINT;
            break;
#endif /* NSS_DISABLE_ECC */
        case CKK_DSA:
        case CKK_DH:
            break;
        default:
            return CKR_ATTRIBUTE_VALUE_INVALID;
    }

    pubKey = &pubKeySpace;
    crv = lg_Attribute2SSecItem(NULL, pubKeyAttr, templ, count, pubKey);
    if (crv != CKR_OK)
        return crv;

#ifndef NSS_DISABLE_ECC
    if (key_type == CKK_EC) {
        SECStatus rv;
        /*
         * for ECC, use the decoded key first.
         */
        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (arena == NULL) {
            crv = CKR_HOST_MEMORY;
            goto done;
        }
        rv = SEC_QuickDERDecodeItem(arena, &pubKey2Space,
                                    SEC_ASN1_GET(SEC_OctetStringTemplate),
                                    pubKey);
        if (rv != SECSuccess) {
            /* decode didn't work, just try the pubKey */
            PORT_FreeArena(arena, PR_FALSE);
            arena = NULL;
        } else {
            /* try the decoded pub key first */
            pubKey = &pubKey2Space;
        }
    }
#endif /* NSS_DISABLE_ECC */

    PORT_Assert(pubKey->data);
    if (pubKey->data == NULL) {
        crv = CKR_ATTRIBUTE_VALUE_INVALID;
        goto done;
    }
    keyHandle = lg_getKeyDB(sdb);
    if (keyHandle == NULL) {
        crv = CKR_TOKEN_WRITE_PROTECTED;
        goto done;
    }
    if (keyHandle->version != 3) {
        unsigned char buf[SHA1_LENGTH];
        SHA1_HashBuf(buf, pubKey->data, pubKey->len);
        PORT_Memcpy(pubKey->data, buf, sizeof(buf));
        pubKey->len = sizeof(buf);
    }
    /* make sure the associated private key already exists */
    /* only works if we are logged in */
    priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey, sdb /*password*/);
#ifndef NSS_DISABLE_ECC
    if (priv == NULL && pubKey == &pubKey2Space) {
        /* no match on the decoded key, match the original pubkey */
        pubKey = &pubKeySpace;
        priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey,
                                            sdb /*password*/);
    }
#endif
    if (priv == NULL) {
        /* the legacy database can only 'store' public keys which already
         * have their corresponding private keys in the database */
        crv = CKR_ATTRIBUTE_VALUE_INVALID;
        goto done;
    }
    lg_nsslowkey_DestroyPrivateKey(priv);
    crv = CKR_OK;

    *handle = lg_mkHandle(sdb, pubKey, LG_TOKEN_TYPE_PUB);

done:
    PORT_Free(pubKeySpace.data);
#ifndef NSS_DISABLE_ECC
    if (arena)
        PORT_FreeArena(arena, PR_FALSE);
#endif

    return crv;
}
예제 #28
0
static long
smime_choose_cipher(CERTCertificate *scert, CERTCertificate **rcerts)
{
    PLArenaPool *poolp;
    long chosen_cipher;
    int *cipher_abilities;
    int *cipher_votes;
    int strong_mapi;
    int rcount, mapi, max;

    if (smime_policy_bits == 0) {
        PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
        return -1;
    }

    chosen_cipher = SMIME_RC2_CBC_40; /* the default, LCD */

    poolp = PORT_NewArena(1024); /* XXX what is right value? */
    if (poolp == NULL)
        goto done;

    cipher_abilities = (int *)PORT_ArenaZAlloc(poolp,
                                               smime_symmetric_count * sizeof(int));
    if (cipher_abilities == NULL)
        goto done;

    cipher_votes = (int *)PORT_ArenaZAlloc(poolp,
                                           smime_symmetric_count * sizeof(int));
    if (cipher_votes == NULL)
        goto done;

    /*
     * XXX Should have a #define somewhere which specifies default
     * strong cipher.  (Or better, a way to configure.)
     */

    /* Make triple-DES the strong cipher. */
    strong_mapi = smime_mapi_by_cipher(SMIME_DES_EDE3_168);

    PORT_Assert(strong_mapi >= 0);

    for (rcount = 0; rcerts[rcount] != NULL; rcount++) {
        SECItem *profile;
        smime_capability **caps;
        int capi, pref;
        SECStatus dstat;

        pref = smime_symmetric_count;
        profile = CERT_FindSMimeProfile(rcerts[rcount]);
        if (profile != NULL && profile->data != NULL && profile->len > 0) {
            caps = NULL;
            dstat = SEC_QuickDERDecodeItem(poolp, &caps,
                                           smime_capabilities_template,
                                           profile);
            if (dstat == SECSuccess && caps != NULL) {
                for (capi = 0; caps[capi] != NULL; capi++) {
                    smime_fill_capability(caps[capi]);
                    mapi = smime_mapi_by_cipher(caps[capi]->cipher);
                    if (mapi >= 0) {
                        cipher_abilities[mapi]++;
                        cipher_votes[mapi] += pref;
                        --pref;
                    }
                }
            }
        } else {
            SECKEYPublicKey *key;
            unsigned int pklen_bits;

            /*
             * XXX This is probably only good for RSA keys.  What I would
             * really like is a function to just say;  Is the public key in
             * this cert an export-length key?  Then I would not have to
             * know things like the value 512, or the kind of key, or what
             * a subjectPublicKeyInfo is, etc.
             */
            key = CERT_ExtractPublicKey(rcerts[rcount]);
            if (key != NULL) {
                pklen_bits = SECKEY_PublicKeyStrength(key) * 8;
                SECKEY_DestroyPublicKey(key);

                if (pklen_bits > 512) {
                    cipher_abilities[strong_mapi]++;
                    cipher_votes[strong_mapi] += pref;
                }
            }
        }
        if (profile != NULL)
            SECITEM_FreeItem(profile, PR_TRUE);
    }

    max = 0;
    for (mapi = 0; mapi < smime_symmetric_count; mapi++) {
        if (cipher_abilities[mapi] != rcount)
            continue;
        if (!smime_cipher_allowed(smime_cipher_maps[mapi].cipher))
            continue;
        if (cipher_votes[mapi] > max) {
            chosen_cipher = smime_cipher_maps[mapi].cipher;
            max = cipher_votes[mapi];
        } /* XXX else if a tie, let scert break it? */
    }

done:
    if (poolp != NULL)
        PORT_FreeArena(poolp, PR_FALSE);

    return chosen_cipher;
}
예제 #29
0
/* find a URL extension in the cert
 */
char *
CERT_FindCertURLExtension(CERTCertificate *cert, SECOidTag tag)
{
    SECStatus rv;
    SECItem urlitem = {siBuffer,0};
    SECItem urlstringitem = {siBuffer,0};
    PLArenaPool *arena = NULL;
    char *urlstring = NULL;
    char *str;
    int len;
    
    if (!cert) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if ( ! arena ) {
	goto loser;
    }
    
    rv = cert_FindExtension(cert->extensions, tag, &urlitem);
    if ( rv != SECSuccess ) {
	goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, &urlstringitem,
                                SEC_ASN1_GET(SEC_IA5StringTemplate), &urlitem);

    if ( rv != SECSuccess ) {
	goto loser;
    }
    
    len = urlstringitem.len + 1;
    
    str = urlstring = (char *)PORT_Alloc(len);
    if ( urlstring == NULL ) {
	goto loser;
    }
    
    /* copy the URL */
    PORT_Memcpy(str, urlstringitem.data, urlstringitem.len);
    str += urlstringitem.len;
    
    *str = '\0';
    goto done;
    
loser:
    if ( urlstring ) {
	PORT_Free(urlstring);
    }
    
    urlstring = NULL;
done:
    if ( arena ) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    if ( urlitem.data ) {
	PORT_Free(urlitem.data);
    }

    return(urlstring);
}
예제 #30
0
SECStatus
SEC_ReadCertSequence(SECItem *certsItem, CERTImportCertificateFunc f, void *arg)
{
    SECStatus rv;
    SECItem **certs;
    int count;
    SECItem **rawCerts = NULL;
    PRArenaPool *arena;
    SEC_PKCS7ContentInfo *contentInfo = NULL;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
	return SECFailure;
    }

    contentInfo = SEC_PKCS7DecodeItem(certsItem, NULL, NULL, NULL, NULL, NULL, 
				      NULL, NULL);
    if ( contentInfo == NULL ) {
	goto loser;
    }

    if ( SEC_PKCS7ContentType (contentInfo) != SEC_OID_NS_TYPE_CERT_SEQUENCE ) {
	goto loser;
    }


    rv = SEC_QuickDERDecodeItem(arena, &rawCerts, SEC_CertSequenceTemplate,
		    contentInfo->content.data);

    if (rv != SECSuccess) {
	goto loser;
    }

    certs = rawCerts;
    if ( certs ) {
	count = 0;
	
	while ( *certs ) {
	    count++;
	    certs++;
	}
	rv = (* f)(arg, rawCerts, count);
    }
    
    rv = SECSuccess;
    
    goto done;
loser:
    rv = SECFailure;
    
done:
    if ( contentInfo ) {
	SEC_PKCS7DestroyContentInfo(contentInfo);
    }

    if ( arena ) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    
    return(rv);
}