mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-21 22:57:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
48
security/nss/lib/certdb/Makefile
Normal file
48
security/nss/lib/certdb/Makefile
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#! gmake
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include config.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
export:: private_export
|
||||
|
||||
1576
security/nss/lib/certdb/alg1485.c
Normal file
1576
security/nss/lib/certdb/alg1485.c
Normal file
File diff suppressed because it is too large
Load diff
1584
security/nss/lib/certdb/cert.h
Normal file
1584
security/nss/lib/certdb/cert.h
Normal file
File diff suppressed because it is too large
Load diff
3231
security/nss/lib/certdb/certdb.c
Normal file
3231
security/nss/lib/certdb/certdb.c
Normal file
File diff suppressed because it is too large
Load diff
34
security/nss/lib/certdb/certdb.gyp
Normal file
34
security/nss/lib/certdb/certdb.gyp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi'
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'certdb',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'alg1485.c',
|
||||
'certdb.c',
|
||||
'certv3.c',
|
||||
'certxutl.c',
|
||||
'crl.c',
|
||||
'genname.c',
|
||||
'polcyxtn.c',
|
||||
'secname.c',
|
||||
'stanpcertdb.c',
|
||||
'xauthkid.c',
|
||||
'xbsconst.c',
|
||||
'xconst.c'
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports'
|
||||
]
|
||||
}
|
||||
],
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
||||
89
security/nss/lib/certdb/certdb.h
Normal file
89
security/nss/lib/certdb/certdb.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _CERTDB_H_
|
||||
#define _CERTDB_H_
|
||||
|
||||
/* common flags for all types of certificates */
|
||||
#define CERTDB_TERMINAL_RECORD (1u << 0)
|
||||
#define CERTDB_TRUSTED (1u << 1)
|
||||
#define CERTDB_SEND_WARN (1u << 2)
|
||||
#define CERTDB_VALID_CA (1u << 3)
|
||||
#define CERTDB_TRUSTED_CA (1u << 4) /* trusted for issuing server certs */
|
||||
#define CERTDB_NS_TRUSTED_CA (1u << 5)
|
||||
#define CERTDB_USER (1u << 6)
|
||||
#define CERTDB_TRUSTED_CLIENT_CA (1u << 7) /* trusted for issuing client certs */
|
||||
#define CERTDB_INVISIBLE_CA (1u << 8) /* don't show in UI */
|
||||
#define CERTDB_GOVT_APPROVED_CA (1u << 9) /* can do strong crypto in export ver */
|
||||
|
||||
/* old usage, to keep old programs compiling */
|
||||
/* On Windows, Mac, and Linux (and other gcc platforms), we can give compile
|
||||
* time deprecation warnings when applications use the old CERTDB_VALID_PEER
|
||||
* define */
|
||||
#if __GNUC__ > 3
|
||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 5)
|
||||
typedef unsigned int __CERTDB_VALID_PEER __attribute__((deprecated));
|
||||
#else
|
||||
typedef unsigned int __CERTDB_VALID_PEER __attribute__((
|
||||
deprecated("CERTDB_VALID_PEER is now CERTDB_TERMINAL_RECORD")));
|
||||
#endif
|
||||
#define CERTDB_VALID_PEER ((__CERTDB_VALID_PEER)CERTDB_TERMINAL_RECORD)
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#pragma deprecated(CERTDB_VALID_PEER)
|
||||
#endif
|
||||
#define CERTDB_VALID_PEER CERTDB_TERMINAL_RECORD
|
||||
#endif
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
CERTSignedCrl *SEC_FindCrlByKey(CERTCertDBHandle *handle, SECItem *crlKey,
|
||||
int type);
|
||||
|
||||
CERTSignedCrl *SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey,
|
||||
int type);
|
||||
|
||||
CERTSignedCrl *SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl,
|
||||
int type);
|
||||
|
||||
PRBool SEC_CertNicknameConflict(const char *nickname, const SECItem *derSubject,
|
||||
CERTCertDBHandle *handle);
|
||||
CERTSignedCrl *SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl,
|
||||
int type);
|
||||
|
||||
SECStatus SEC_DeletePermCRL(CERTSignedCrl *crl);
|
||||
|
||||
SECStatus SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes,
|
||||
int type);
|
||||
|
||||
SECStatus SEC_DestroyCrl(CERTSignedCrl *crl);
|
||||
|
||||
CERTSignedCrl *SEC_DupCrl(CERTSignedCrl *acrl);
|
||||
|
||||
SECStatus CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
|
||||
CERTCertTrust *trust);
|
||||
|
||||
SECStatus SEC_DeletePermCertificate(CERTCertificate *cert);
|
||||
|
||||
PRBool SEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old);
|
||||
|
||||
/*
|
||||
** Extract the validity times from a CRL
|
||||
** "crl" is the CRL
|
||||
** "notBefore" is the start of the validity period (last update)
|
||||
** "notAfter" is the end of the validity period (next update)
|
||||
*/
|
||||
SECStatus SEC_GetCrlTimes(CERTCrl *crl, PRTime *notBefore, PRTime *notAfter);
|
||||
|
||||
/*
|
||||
** Check the validity times of a crl vs. time 't', allowing
|
||||
** some slop for broken clocks and stuff.
|
||||
** "crl" is the certificate to be checked
|
||||
** "t" is the time to check against
|
||||
*/
|
||||
SECCertTimeValidity SEC_CheckCrlTimes(CERTCrl *crl, PRTime t);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _CERTDB_H_ */
|
||||
381
security/nss/lib/certdb/certi.h
Normal file
381
security/nss/lib/certdb/certi.h
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* certi.h - private data structures for the certificate library
|
||||
*/
|
||||
#ifndef _CERTI_H_
|
||||
#define _CERTI_H_
|
||||
|
||||
#include "certt.h"
|
||||
#include "nssrwlkt.h"
|
||||
|
||||
/*
|
||||
#define GLOBAL_RWLOCK 1
|
||||
*/
|
||||
|
||||
#define DPC_RWLOCK 1
|
||||
|
||||
/* all definitions in this file are subject to change */
|
||||
|
||||
typedef struct OpaqueCRLFieldsStr OpaqueCRLFields;
|
||||
typedef struct CRLEntryCacheStr CRLEntryCache;
|
||||
typedef struct CRLDPCacheStr CRLDPCache;
|
||||
typedef struct CRLIssuerCacheStr CRLIssuerCache;
|
||||
typedef struct CRLCacheStr CRLCache;
|
||||
typedef struct CachedCrlStr CachedCrl;
|
||||
typedef struct NamedCRLCacheStr NamedCRLCache;
|
||||
typedef struct NamedCRLCacheEntryStr NamedCRLCacheEntry;
|
||||
|
||||
struct OpaqueCRLFieldsStr {
|
||||
PRBool partial;
|
||||
PRBool decodingError;
|
||||
PRBool badEntries;
|
||||
PRBool badDER;
|
||||
PRBool badExtensions;
|
||||
PRBool heapDER;
|
||||
};
|
||||
|
||||
typedef struct PreAllocatorStr PreAllocator;
|
||||
|
||||
struct PreAllocatorStr {
|
||||
PRSize len;
|
||||
void* data;
|
||||
PRSize used;
|
||||
PLArenaPool* arena;
|
||||
PRSize extra;
|
||||
};
|
||||
|
||||
/* CRL entry cache.
|
||||
This is the same as an entry plus the next/prev pointers for the hash table
|
||||
*/
|
||||
|
||||
struct CRLEntryCacheStr {
|
||||
CERTCrlEntry entry;
|
||||
CRLEntryCache *prev, *next;
|
||||
};
|
||||
|
||||
#define CRL_CACHE_INVALID_CRLS 0x0001 /* this state will be set \
|
||||
if we have CRL objects with an invalid DER or signature. Can be \
|
||||
cleared if the invalid objects are deleted from the token */
|
||||
#define CRL_CACHE_LAST_FETCH_FAILED 0x0002 /* this state will be set \
|
||||
if the last CRL fetch encountered an error. Can be cleared if a \
|
||||
new fetch succeeds */
|
||||
|
||||
#define CRL_CACHE_OUT_OF_MEMORY 0x0004 /* this state will be set \
|
||||
if we don't have enough memory to build the hash table of entries */
|
||||
|
||||
typedef enum {
|
||||
CRL_OriginToken = 0, /* CRL came from PKCS#11 token */
|
||||
CRL_OriginExplicit = 1 /* CRL was explicitly added to the cache, from RAM */
|
||||
} CRLOrigin;
|
||||
|
||||
typedef enum {
|
||||
dpcacheNoEntry = 0, /* no entry found for this SN */
|
||||
dpcacheFoundEntry = 1, /* entry found for this SN */
|
||||
dpcacheCallerError = 2, /* invalid args */
|
||||
dpcacheInvalidCacheError = 3, /* CRL in cache may be bad DER */
|
||||
/* or unverified */
|
||||
dpcacheEmpty = 4, /* no CRL in cache */
|
||||
dpcacheLookupError = 5 /* internal error */
|
||||
} dpcacheStatus;
|
||||
|
||||
struct CachedCrlStr {
|
||||
CERTSignedCrl* crl;
|
||||
CRLOrigin origin;
|
||||
/* hash table of entries. We use a PLHashTable and pre-allocate the
|
||||
required amount of memory in one shot, so that our allocator can
|
||||
simply pass offsets into it when hashing.
|
||||
|
||||
This won't work anymore when we support delta CRLs and iCRLs, because
|
||||
the size of the hash table will vary over time. At that point, the best
|
||||
solution will be to allocate large CRLEntry structures by modifying
|
||||
the DER decoding template. The extra space would be for next/prev
|
||||
pointers. This would allow entries from different CRLs to be mixed in
|
||||
the same hash table.
|
||||
*/
|
||||
PLHashTable* entries;
|
||||
PreAllocator* prebuffer; /* big pre-allocated buffer mentioned above */
|
||||
PRBool sigChecked; /* this CRL signature has already been checked */
|
||||
PRBool sigValid; /* signature verification status .
|
||||
Only meaningful if checked is PR_TRUE . */
|
||||
PRBool unbuildable; /* Avoid using assosiated CRL is it fails
|
||||
* a decoding step */
|
||||
};
|
||||
|
||||
/* CRL distribution point cache object
|
||||
This is a cache of CRL entries for a given distribution point of an issuer
|
||||
It is built from a collection of one full and 0 or more delta CRLs.
|
||||
*/
|
||||
|
||||
struct CRLDPCacheStr {
|
||||
#ifdef DPC_RWLOCK
|
||||
NSSRWLock* lock;
|
||||
#else
|
||||
PRLock* lock;
|
||||
#endif
|
||||
SECItem* issuerDERCert; /* issuer DER cert. Don't hold a reference
|
||||
to the actual cert so the trust can be
|
||||
updated on the cert automatically.
|
||||
XXX there may be multiple issuer certs,
|
||||
with different validity dates. Also
|
||||
need to deal with SKID/AKID . See
|
||||
bugzilla 217387, 233118 */
|
||||
|
||||
CERTCertDBHandle* dbHandle;
|
||||
|
||||
SECItem* subject; /* DER of issuer subject */
|
||||
SECItem* distributionPoint; /* DER of distribution point. This may be
|
||||
NULL when distribution points aren't
|
||||
in use (ie. the CA has a single CRL).
|
||||
Currently not used. */
|
||||
|
||||
/* array of full CRLs matching this distribution point */
|
||||
PRUint32 ncrls; /* total number of CRLs in crls */
|
||||
CachedCrl** crls; /* array of all matching CRLs */
|
||||
/* XCRL With iCRLs and multiple DPs, the CRL can be shared accross several
|
||||
issuers. In the future, we'll need to globally recycle the CRL in a
|
||||
separate list in order to avoid extra lookups, decodes, and copies */
|
||||
|
||||
/* pointers to good decoded CRLs used to build the cache */
|
||||
CachedCrl* selected; /* full CRL selected for use in the cache */
|
||||
#if 0
|
||||
/* for future use */
|
||||
PRInt32 numdeltas; /* number of delta CRLs used for the cache */
|
||||
CachedCrl** deltas; /* delta CRLs used for the cache */
|
||||
#endif
|
||||
/* cache invalidity bitflag */
|
||||
PRUint16 invalid; /* this state will be set if either
|
||||
CRL_CACHE_INVALID_CRLS or CRL_CACHE_LAST_FETCH_FAILED is set.
|
||||
In those cases, all certs are considered to have unknown status.
|
||||
The invalid state can only be cleared during an update if all
|
||||
error states are cleared */
|
||||
PRBool refresh; /* manual refresh from tokens has been forced */
|
||||
PRBool mustchoose; /* trigger reselection algorithm, for case when
|
||||
RAM CRL objects are dropped from the cache */
|
||||
PRTime lastfetch; /* time a CRL token fetch was last performed */
|
||||
PRTime lastcheck; /* time CRL token objects were last checked for
|
||||
existence */
|
||||
};
|
||||
|
||||
/* CRL issuer cache object
|
||||
This object tracks all the distribution point caches for a given issuer.
|
||||
XCRL once we support multiple issuing distribution points, this object
|
||||
will be a hash table. For now, it just holds the single CRL distribution
|
||||
point cache structure.
|
||||
*/
|
||||
|
||||
struct CRLIssuerCacheStr {
|
||||
SECItem* subject; /* DER of issuer subject */
|
||||
CRLDPCache* dpp;
|
||||
};
|
||||
|
||||
/* CRL revocation cache object
|
||||
This object tracks all the issuer caches
|
||||
*/
|
||||
|
||||
struct CRLCacheStr {
|
||||
#ifdef GLOBAL_RWLOCK
|
||||
NSSRWLock* lock;
|
||||
#else
|
||||
PRLock* lock;
|
||||
#endif
|
||||
/* hash table of issuer to CRLIssuerCacheStr,
|
||||
indexed by issuer DER subject */
|
||||
PLHashTable* issuers;
|
||||
};
|
||||
|
||||
SECStatus InitCRLCache(void);
|
||||
SECStatus ShutdownCRLCache(void);
|
||||
|
||||
/* Returns a pointer to an environment-like string, a series of
|
||||
** null-terminated strings, terminated by a zero-length string.
|
||||
** This function is intended to be internal to NSS.
|
||||
*/
|
||||
extern char* cert_GetCertificateEmailAddresses(CERTCertificate* cert);
|
||||
|
||||
/*
|
||||
* These functions are used to map subjectKeyID extension values to certs
|
||||
* and to keep track of the checks for user certificates in each slot
|
||||
*/
|
||||
SECStatus cert_CreateSubjectKeyIDHashTable(void);
|
||||
|
||||
SECStatus cert_AddSubjectKeyIDMapping(SECItem* subjKeyID,
|
||||
CERTCertificate* cert);
|
||||
|
||||
SECStatus cert_UpdateSubjectKeyIDSlotCheck(SECItem* slotid, int series);
|
||||
|
||||
int cert_SubjectKeyIDSlotCheckSeries(SECItem* slotid);
|
||||
|
||||
/*
|
||||
* Call this function to remove an entry from the mapping table.
|
||||
*/
|
||||
SECStatus cert_RemoveSubjectKeyIDMapping(SECItem* subjKeyID);
|
||||
|
||||
SECStatus cert_DestroySubjectKeyIDHashTable(void);
|
||||
|
||||
SECItem* cert_FindDERCertBySubjectKeyID(SECItem* subjKeyID);
|
||||
|
||||
/* return maximum length of AVA value based on its type OID tag. */
|
||||
extern int cert_AVAOidTagToMaxLen(SECOidTag tag);
|
||||
|
||||
/* Make an AVA, allocated from pool, from OID and DER encoded value */
|
||||
extern CERTAVA* CERT_CreateAVAFromRaw(PLArenaPool* pool, const SECItem* OID,
|
||||
const SECItem* value);
|
||||
|
||||
/* Make an AVA from binary input specified by SECItem */
|
||||
extern CERTAVA* CERT_CreateAVAFromSECItem(PLArenaPool* arena, SECOidTag kind,
|
||||
int valueType, SECItem* value);
|
||||
|
||||
/*
|
||||
* get a DPCache object for the given issuer subject and dp
|
||||
* Automatically creates the cache object if it doesn't exist yet.
|
||||
*/
|
||||
SECStatus AcquireDPCache(CERTCertificate* issuer, const SECItem* subject,
|
||||
const SECItem* dp, PRTime t, void* wincx,
|
||||
CRLDPCache** dpcache, PRBool* writeLocked);
|
||||
|
||||
/* check if a particular SN is in the CRL cache and return its entry */
|
||||
dpcacheStatus DPCache_Lookup(CRLDPCache* cache, const SECItem* sn,
|
||||
CERTCrlEntry** returned);
|
||||
|
||||
/* release a DPCache object that was previously acquired */
|
||||
void ReleaseDPCache(CRLDPCache* dpcache, PRBool writeLocked);
|
||||
|
||||
/*
|
||||
* map Stan errors into NSS errors
|
||||
* This function examines the stan error stack and automatically sets
|
||||
* PORT_SetError(); to the appropriate SEC_ERROR value.
|
||||
*/
|
||||
void CERT_MapStanError();
|
||||
|
||||
/* Like CERT_VerifyCert, except with an additional argument, flags. The
|
||||
* flags are defined immediately below.
|
||||
*/
|
||||
SECStatus cert_VerifyCertWithFlags(CERTCertDBHandle* handle,
|
||||
CERTCertificate* cert, PRBool checkSig,
|
||||
SECCertUsage certUsage, PRTime t,
|
||||
PRUint32 flags, void* wincx,
|
||||
CERTVerifyLog* log);
|
||||
|
||||
/* Use the default settings.
|
||||
* cert_VerifyCertWithFlags(..., CERT_VERIFYCERT_USE_DEFAULTS, ...) is
|
||||
* equivalent to CERT_VerifyCert(...);
|
||||
*/
|
||||
#define CERT_VERIFYCERT_USE_DEFAULTS 0
|
||||
|
||||
/* Skip all the OCSP checks during certificate verification, regardless of
|
||||
* the global OCSP settings. By default, certificate |cert| will have its
|
||||
* revocation status checked via OCSP according to the global OCSP settings.
|
||||
*
|
||||
* OCSP checking is always skipped when certUsage is certUsageStatusResponder.
|
||||
*/
|
||||
#define CERT_VERIFYCERT_SKIP_OCSP 1
|
||||
|
||||
/* Interface function for libpkix cert validation engine:
|
||||
* cert_verify wrapper. */
|
||||
SECStatus cert_VerifyCertChainPkix(CERTCertificate* cert, PRBool checkSig,
|
||||
SECCertUsage requiredUsage, PRTime time,
|
||||
void* wincx, CERTVerifyLog* log,
|
||||
PRBool* sigError, PRBool* revoked);
|
||||
|
||||
SECStatus cert_InitLocks(void);
|
||||
|
||||
SECStatus cert_DestroyLocks(void);
|
||||
|
||||
/*
|
||||
* fill in nsCertType field of the cert based on the cert extension
|
||||
*/
|
||||
extern SECStatus cert_GetCertType(CERTCertificate* cert);
|
||||
|
||||
/*
|
||||
* compute and return the value of nsCertType for cert, but do not
|
||||
* update the CERTCertificate.
|
||||
*/
|
||||
extern PRUint32 cert_ComputeCertType(CERTCertificate* cert);
|
||||
|
||||
void cert_AddToVerifyLog(CERTVerifyLog* log, CERTCertificate* cert,
|
||||
long errorCode, unsigned int depth, void* arg);
|
||||
|
||||
/* Insert a DER CRL into the CRL cache, and take ownership of it.
|
||||
*
|
||||
* cert_CacheCRLByGeneralName takes ownership of the memory in crl argument
|
||||
* completely. crl must be freeable by SECITEM_FreeItem. It will be freed
|
||||
* immediately if it is rejected from the CRL cache, or later during cache
|
||||
* updates when a new crl is available, or at shutdown time.
|
||||
*
|
||||
* canonicalizedName represents the source of the CRL, a GeneralName.
|
||||
* The format of the encoding is not restricted, but all callers of
|
||||
* cert_CacheCRLByGeneralName and cert_FindCRLByGeneralName must use
|
||||
* the same encoding. To facilitate X.500 name matching, a canonicalized
|
||||
* encoding of the GeneralName should be used, if available.
|
||||
*/
|
||||
|
||||
SECStatus cert_CacheCRLByGeneralName(CERTCertDBHandle* dbhandle, SECItem* crl,
|
||||
const SECItem* canonicalizedName);
|
||||
|
||||
struct NamedCRLCacheStr {
|
||||
PRLock* lock;
|
||||
PLHashTable* entries;
|
||||
};
|
||||
|
||||
/* NamedCRLCacheEntryStr is filled in by cert_CacheCRLByGeneralName,
|
||||
* and read by cert_FindCRLByGeneralName */
|
||||
struct NamedCRLCacheEntryStr {
|
||||
SECItem* canonicalizedName;
|
||||
SECItem* crl; /* DER, kept only if CRL
|
||||
* is successfully cached */
|
||||
PRBool inCRLCache;
|
||||
PRTime successfulInsertionTime; /* insertion time */
|
||||
PRTime lastAttemptTime; /* time of last call to
|
||||
cert_CacheCRLByGeneralName with this name */
|
||||
PRBool badDER; /* ASN.1 error */
|
||||
PRBool dupe; /* matching DER CRL already in CRL cache */
|
||||
PRBool unsupported; /* IDP, delta, any other reason */
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
certRevocationStatusRevoked = 0,
|
||||
certRevocationStatusValid = 1,
|
||||
certRevocationStatusUnknown = 2
|
||||
} CERTRevocationStatus;
|
||||
|
||||
/* Returns detailed status of the cert(revStatus variable). Tells if
|
||||
* issuer cache has OriginFetchedWithTimeout crl in it. */
|
||||
SECStatus cert_CheckCertRevocationStatus(CERTCertificate* cert,
|
||||
CERTCertificate* issuer,
|
||||
const SECItem* dp, PRTime t,
|
||||
void* wincx,
|
||||
CERTRevocationStatus* revStatus,
|
||||
CERTCRLEntryReasonCode* revReason);
|
||||
|
||||
SECStatus cert_AcquireNamedCRLCache(NamedCRLCache** returned);
|
||||
|
||||
/* cert_FindCRLByGeneralName must be called only while the named cache is
|
||||
* acquired, and the entry is only valid until cache is released.
|
||||
*/
|
||||
SECStatus cert_FindCRLByGeneralName(NamedCRLCache* ncc,
|
||||
const SECItem* canonicalizedName,
|
||||
NamedCRLCacheEntry** retEntry);
|
||||
|
||||
SECStatus cert_ReleaseNamedCRLCache(NamedCRLCache* ncc);
|
||||
|
||||
/* This is private for now. Maybe shoule be public. */
|
||||
CERTGeneralName* cert_GetSubjectAltNameList(const CERTCertificate* cert,
|
||||
PLArenaPool* arena);
|
||||
|
||||
/* Count DNS names and IP addresses in a list of GeneralNames */
|
||||
PRUint32 cert_CountDNSPatterns(CERTGeneralName* firstName);
|
||||
|
||||
/*
|
||||
* returns the trust status of the leaf certificate based on usage.
|
||||
* If the leaf is explicitly untrusted, this function will fail and
|
||||
* failedFlags will be set to the trust bit value that lead to the failure.
|
||||
* If the leaf is trusted, isTrusted is set to true and the function returns
|
||||
* SECSuccess. This function does not check if the cert is fit for a
|
||||
* particular usage.
|
||||
*/
|
||||
SECStatus cert_CheckLeafTrust(CERTCertificate* cert, SECCertUsage usage,
|
||||
unsigned int* failedFlags, PRBool* isTrusted);
|
||||
|
||||
#endif /* _CERTI_H_ */
|
||||
1328
security/nss/lib/certdb/certt.h
Normal file
1328
security/nss/lib/certdb/certt.h
Normal file
File diff suppressed because it is too large
Load diff
222
security/nss/lib/certdb/certv3.c
Normal file
222
security/nss/lib/certdb/certv3.c
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Code for dealing with X509.V3 extensions.
|
||||
*/
|
||||
|
||||
#include "cert.h"
|
||||
#include "secitem.h"
|
||||
#include "secoid.h"
|
||||
#include "secder.h"
|
||||
#include "secasn1.h"
|
||||
#include "certxutl.h"
|
||||
#include "secerr.h"
|
||||
|
||||
SECStatus
|
||||
CERT_FindCertExtensionByOID(CERTCertificate *cert, SECItem *oid, SECItem *value)
|
||||
{
|
||||
return (cert_FindExtensionByOID(cert->extensions, oid, value));
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_FindCertExtension(const CERTCertificate *cert, int tag, SECItem *value)
|
||||
{
|
||||
return (cert_FindExtension(cert->extensions, tag, value));
|
||||
}
|
||||
|
||||
static void
|
||||
SetExts(void *object, CERTCertExtension **exts)
|
||||
{
|
||||
CERTCertificate *cert = (CERTCertificate *)object;
|
||||
|
||||
cert->extensions = exts;
|
||||
DER_SetUInteger(cert->arena, &(cert->version), SEC_CERTIFICATE_VERSION_3);
|
||||
}
|
||||
|
||||
void *
|
||||
CERT_StartCertExtensions(CERTCertificate *cert)
|
||||
{
|
||||
return (cert_StartExtensions((void *)cert, cert->arena, SetExts));
|
||||
}
|
||||
|
||||
/*
|
||||
* get the value of the Netscape Certificate Type Extension
|
||||
*/
|
||||
SECStatus
|
||||
CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem)
|
||||
{
|
||||
|
||||
return (CERT_FindBitStringExtension(
|
||||
cert->extensions, SEC_OID_NS_CERT_EXT_CERT_TYPE, retItem));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* get the value of the X.509 v3 Key Usage Extension
|
||||
*/
|
||||
SECStatus
|
||||
CERT_FindKeyUsageExtension(CERTCertificate *cert, SECItem *retItem)
|
||||
{
|
||||
|
||||
return (CERT_FindBitStringExtension(cert->extensions,
|
||||
SEC_OID_X509_KEY_USAGE, retItem));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
PORTCheapArenaPool tmpArena;
|
||||
PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
|
||||
rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &decodedValue,
|
||||
SEC_ASN1_GET(SEC_OctetStringTemplate),
|
||||
&encodedValue);
|
||||
if (rv == SECSuccess) {
|
||||
rv = SECITEM_CopyItem(NULL, retItem, &decodedValue);
|
||||
}
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
}
|
||||
SECITEM_FreeItem(&encodedValue, PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_FindBasicConstraintExten(CERTCertificate *cert,
|
||||
CERTBasicConstraints *value)
|
||||
{
|
||||
SECItem encodedExtenValue;
|
||||
SECStatus rv;
|
||||
|
||||
encodedExtenValue.data = NULL;
|
||||
encodedExtenValue.len = 0;
|
||||
|
||||
rv = cert_FindExtension(cert->extensions, SEC_OID_X509_BASIC_CONSTRAINTS,
|
||||
&encodedExtenValue);
|
||||
if (rv != SECSuccess) {
|
||||
return (rv);
|
||||
}
|
||||
|
||||
rv = CERT_DecodeBasicConstraintValue(value, &encodedExtenValue);
|
||||
|
||||
/* free the raw extension data */
|
||||
PORT_Free(encodedExtenValue.data);
|
||||
encodedExtenValue.data = NULL;
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
CERTAuthKeyID *
|
||||
CERT_FindAuthKeyIDExten(PLArenaPool *arena, CERTCertificate *cert)
|
||||
{
|
||||
SECItem encodedExtenValue;
|
||||
SECStatus rv;
|
||||
CERTAuthKeyID *ret;
|
||||
|
||||
encodedExtenValue.data = NULL;
|
||||
encodedExtenValue.len = 0;
|
||||
|
||||
rv = cert_FindExtension(cert->extensions, SEC_OID_X509_AUTH_KEY_ID,
|
||||
&encodedExtenValue);
|
||||
if (rv != SECSuccess) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ret = CERT_DecodeAuthKeyID(arena, &encodedExtenValue);
|
||||
|
||||
PORT_Free(encodedExtenValue.data);
|
||||
encodedExtenValue.data = NULL;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_CheckCertUsage(CERTCertificate *cert, unsigned char usage)
|
||||
{
|
||||
SECItem keyUsage;
|
||||
SECStatus rv;
|
||||
|
||||
/* There is no extension, v1 or v2 certificate */
|
||||
if (cert->extensions == NULL) {
|
||||
return (SECSuccess);
|
||||
}
|
||||
|
||||
keyUsage.data = NULL;
|
||||
|
||||
/* This code formerly ignored the Key Usage extension if it was
|
||||
** marked non-critical. That was wrong. Since we do understand it,
|
||||
** we are obligated to honor it, whether or not it is critical.
|
||||
*/
|
||||
rv = CERT_FindKeyUsageExtension(cert, &keyUsage);
|
||||
if (rv == SECFailure) {
|
||||
rv = (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) ? SECSuccess
|
||||
: SECFailure;
|
||||
} else if (!(keyUsage.data[0] & usage)) {
|
||||
PORT_SetError(SEC_ERROR_CERT_USAGES_INVALID);
|
||||
rv = SECFailure;
|
||||
}
|
||||
PORT_Free(keyUsage.data);
|
||||
return (rv);
|
||||
}
|
||||
493
security/nss/lib/certdb/certxutl.c
Normal file
493
security/nss/lib/certdb/certxutl.c
Normal file
|
|
@ -0,0 +1,493 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Certificate Extensions handling code
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cert.h"
|
||||
#include "secitem.h"
|
||||
#include "secoid.h"
|
||||
#include "secder.h"
|
||||
#include "secasn1.h"
|
||||
#include "certxutl.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#ifdef OLD
|
||||
#include "ocspti.h" /* XXX a better extensions interface would not
|
||||
* require knowledge of data structures of callers */
|
||||
#endif
|
||||
|
||||
static CERTCertExtension *
|
||||
GetExtension(CERTCertExtension **extensions, SECItem *oid)
|
||||
{
|
||||
CERTCertExtension **exts;
|
||||
CERTCertExtension *ext = NULL;
|
||||
SECComparison comp;
|
||||
|
||||
exts = extensions;
|
||||
|
||||
if (exts) {
|
||||
while (*exts) {
|
||||
ext = *exts;
|
||||
comp = SECITEM_CompareItem(oid, &ext->id);
|
||||
if (comp == SECEqual)
|
||||
break;
|
||||
|
||||
exts++;
|
||||
}
|
||||
return (*exts ? ext : NULL);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
cert_FindExtensionByOID(CERTCertExtension **extensions, SECItem *oid,
|
||||
SECItem *value)
|
||||
{
|
||||
CERTCertExtension *ext;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
ext = GetExtension(extensions, oid);
|
||||
if (ext == NULL) {
|
||||
PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
|
||||
return (SECFailure);
|
||||
}
|
||||
if (value)
|
||||
rv = SECITEM_CopyItem(NULL, value, &ext->value);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_GetExtenCriticality(CERTCertExtension **extensions, int tag,
|
||||
PRBool *isCritical)
|
||||
{
|
||||
CERTCertExtension *ext;
|
||||
SECOidData *oid;
|
||||
|
||||
if (!isCritical)
|
||||
return (SECSuccess);
|
||||
|
||||
/* find the extension in the extensions list */
|
||||
oid = SECOID_FindOIDByTag((SECOidTag)tag);
|
||||
if (!oid) {
|
||||
return (SECFailure);
|
||||
}
|
||||
ext = GetExtension(extensions, &oid->oid);
|
||||
if (ext == NULL) {
|
||||
PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
|
||||
return (SECFailure);
|
||||
}
|
||||
|
||||
/* If the criticality is omitted, then it is false by default.
|
||||
ex->critical.data is NULL */
|
||||
if (ext->critical.data == NULL)
|
||||
*isCritical = PR_FALSE;
|
||||
else
|
||||
*isCritical = (ext->critical.data[0] == 0xff) ? PR_TRUE : PR_FALSE;
|
||||
return (SECSuccess);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
cert_FindExtension(CERTCertExtension **extensions, int tag, SECItem *value)
|
||||
{
|
||||
SECOidData *oid;
|
||||
|
||||
oid = SECOID_FindOIDByTag((SECOidTag)tag);
|
||||
if (!oid) {
|
||||
return (SECFailure);
|
||||
}
|
||||
|
||||
return (cert_FindExtensionByOID(extensions, &oid->oid, value));
|
||||
}
|
||||
|
||||
typedef struct _extNode {
|
||||
struct _extNode *next;
|
||||
CERTCertExtension *ext;
|
||||
} extNode;
|
||||
|
||||
typedef struct {
|
||||
void (*setExts)(void *object, CERTCertExtension **exts);
|
||||
void *object;
|
||||
PLArenaPool *ownerArena;
|
||||
PLArenaPool *arena;
|
||||
extNode *head;
|
||||
int count;
|
||||
} extRec;
|
||||
|
||||
/*
|
||||
* cert_StartExtensions
|
||||
*
|
||||
* NOTE: This interface changed significantly to remove knowledge
|
||||
* about callers data structures (owner objects)
|
||||
*/
|
||||
void *
|
||||
cert_StartExtensions(void *owner, PLArenaPool *ownerArena,
|
||||
void (*setExts)(void *object, CERTCertExtension **exts))
|
||||
{
|
||||
PLArenaPool *arena;
|
||||
extRec *handle;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
handle = (extRec *)PORT_ArenaAlloc(arena, sizeof(extRec));
|
||||
if (!handle) {
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
handle->object = owner;
|
||||
handle->ownerArena = ownerArena;
|
||||
handle->setExts = setExts;
|
||||
|
||||
handle->arena = arena;
|
||||
handle->head = 0;
|
||||
handle->count = 0;
|
||||
|
||||
return (handle);
|
||||
}
|
||||
|
||||
static unsigned char hextrue = 0xff;
|
||||
|
||||
/*
|
||||
* Note - assumes that data pointed to by oid->data will not move
|
||||
*/
|
||||
SECStatus
|
||||
CERT_AddExtensionByOID(void *exthandle, SECItem *oid, SECItem *value,
|
||||
PRBool critical, PRBool copyData)
|
||||
{
|
||||
CERTCertExtension *ext;
|
||||
SECStatus rv;
|
||||
extNode *node;
|
||||
extRec *handle;
|
||||
|
||||
handle = (extRec *)exthandle;
|
||||
|
||||
/* allocate space for extension and list node */
|
||||
ext = (CERTCertExtension *)PORT_ArenaZAlloc(handle->ownerArena,
|
||||
sizeof(CERTCertExtension));
|
||||
if (!ext) {
|
||||
return (SECFailure);
|
||||
}
|
||||
|
||||
node = (extNode *)PORT_ArenaAlloc(handle->arena, sizeof(extNode));
|
||||
if (!node) {
|
||||
return (SECFailure);
|
||||
}
|
||||
|
||||
/* add to list */
|
||||
node->next = handle->head;
|
||||
handle->head = node;
|
||||
|
||||
/* point to ext struct */
|
||||
node->ext = ext;
|
||||
|
||||
/* set critical field */
|
||||
if (critical) {
|
||||
ext->critical.data = (unsigned char *)&hextrue;
|
||||
ext->critical.len = 1;
|
||||
}
|
||||
|
||||
/* set object ID of the extension and its value */
|
||||
if (copyData) {
|
||||
rv = SECITEM_CopyItem(handle->ownerArena, &ext->id, oid);
|
||||
if (rv) {
|
||||
return (SECFailure);
|
||||
}
|
||||
|
||||
rv = SECITEM_CopyItem(handle->ownerArena, &ext->value, value);
|
||||
if (rv) {
|
||||
return (SECFailure);
|
||||
}
|
||||
} else {
|
||||
ext->id = *oid;
|
||||
ext->value = *value;
|
||||
}
|
||||
|
||||
handle->count++;
|
||||
|
||||
return (SECSuccess);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_AddExtension(void *exthandle, int idtag, SECItem *value, PRBool critical,
|
||||
PRBool copyData)
|
||||
{
|
||||
SECOidData *oid;
|
||||
|
||||
oid = SECOID_FindOIDByTag((SECOidTag)idtag);
|
||||
if (!oid) {
|
||||
return (SECFailure);
|
||||
}
|
||||
|
||||
return (CERT_AddExtensionByOID(exthandle, &oid->oid, value, critical,
|
||||
copyData));
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeAndAddExtension(void *exthandle, int idtag, void *value,
|
||||
PRBool critical, const SEC_ASN1Template *atemplate)
|
||||
{
|
||||
extRec *handle;
|
||||
SECItem *encitem;
|
||||
|
||||
handle = (extRec *)exthandle;
|
||||
|
||||
encitem = SEC_ASN1EncodeItem(handle->ownerArena, NULL, value, atemplate);
|
||||
if (encitem == NULL) {
|
||||
return (SECFailure);
|
||||
}
|
||||
|
||||
return CERT_AddExtension(exthandle, idtag, encitem, critical, PR_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
PrepareBitStringForEncoding(SECItem *bitsmap, SECItem *value)
|
||||
{
|
||||
unsigned char onebyte;
|
||||
unsigned int i, len = 0;
|
||||
|
||||
/* to prevent warning on some platform at compile time */
|
||||
onebyte = '\0';
|
||||
/* Get the position of the right-most turn-on bit */
|
||||
for (i = 0; i < (value->len) * 8; ++i) {
|
||||
if (i % 8 == 0)
|
||||
onebyte = value->data[i / 8];
|
||||
if (onebyte & 0x80)
|
||||
len = i;
|
||||
onebyte <<= 1;
|
||||
}
|
||||
bitsmap->data = value->data;
|
||||
/* Add one here since we work with base 1 */
|
||||
bitsmap->len = len + 1;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeAndAddBitStrExtension(void *exthandle, int idtag, SECItem *value,
|
||||
PRBool critical)
|
||||
{
|
||||
SECItem bitsmap;
|
||||
|
||||
PrepareBitStringForEncoding(&bitsmap, value);
|
||||
return (CERT_EncodeAndAddExtension(exthandle, idtag, &bitsmap, critical,
|
||||
SEC_ASN1_GET(SEC_BitStringTemplate)));
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_FinishExtensions(void *exthandle)
|
||||
{
|
||||
extRec *handle;
|
||||
extNode *node;
|
||||
CERTCertExtension **exts;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
handle = (extRec *)exthandle;
|
||||
|
||||
/* allocate space for extensions array */
|
||||
exts = PORT_ArenaNewArray(handle->ownerArena, CERTCertExtension *,
|
||||
handle->count + 1);
|
||||
if (exts == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* put extensions in owner object and update its version number */
|
||||
|
||||
#ifdef OLD
|
||||
switch (handle->type) {
|
||||
case CertificateExtensions:
|
||||
handle->owner.cert->extensions = exts;
|
||||
DER_SetUInteger(ownerArena, &(handle->owner.cert->version),
|
||||
SEC_CERTIFICATE_VERSION_3);
|
||||
break;
|
||||
case CrlExtensions:
|
||||
handle->owner.crl->extensions = exts;
|
||||
DER_SetUInteger(ownerArena, &(handle->owner.crl->version),
|
||||
SEC_CRL_VERSION_2);
|
||||
break;
|
||||
case OCSPRequestExtensions:
|
||||
handle->owner.request->tbsRequest->requestExtensions = exts;
|
||||
break;
|
||||
case OCSPSingleRequestExtensions:
|
||||
handle->owner.singleRequest->singleRequestExtensions = exts;
|
||||
break;
|
||||
case OCSPResponseSingleExtensions:
|
||||
handle->owner.singleResponse->singleExtensions = exts;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
handle->setExts(handle->object, exts);
|
||||
|
||||
/* update the version number */
|
||||
|
||||
/* copy each extension pointer */
|
||||
node = handle->head;
|
||||
while (node) {
|
||||
*exts = node->ext;
|
||||
|
||||
node = node->next;
|
||||
exts++;
|
||||
}
|
||||
|
||||
/* terminate the array of extensions */
|
||||
*exts = 0;
|
||||
|
||||
rv = SECSuccess;
|
||||
|
||||
loser:
|
||||
/* free working arena */
|
||||
PORT_FreeArena(handle->arena, PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_MergeExtensions(void *exthandle, CERTCertExtension **extensions)
|
||||
{
|
||||
CERTCertExtension *ext;
|
||||
SECStatus rv = SECSuccess;
|
||||
SECOidTag tag;
|
||||
extNode *node;
|
||||
extRec *handle = exthandle;
|
||||
|
||||
if (!exthandle || !extensions) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
while ((ext = *extensions++) != NULL) {
|
||||
tag = SECOID_FindOIDTag(&ext->id);
|
||||
for (node = handle->head; node != NULL; node = node->next) {
|
||||
if (tag == 0) {
|
||||
if (SECITEM_ItemsAreEqual(&ext->id, &node->ext->id))
|
||||
break;
|
||||
} else {
|
||||
if (SECOID_FindOIDTag(&node->ext->id) == tag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node == NULL) {
|
||||
PRBool critical = (ext->critical.len != 0 &&
|
||||
ext->critical.data[ext->critical.len - 1] != 0);
|
||||
if (critical && tag == SEC_OID_UNKNOWN) {
|
||||
PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
/* add to list */
|
||||
rv = CERT_AddExtensionByOID(exthandle, &ext->id, &ext->value,
|
||||
critical, PR_TRUE);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the value of the Netscape Certificate Type Extension
|
||||
*/
|
||||
SECStatus
|
||||
CERT_FindBitStringExtension(CERTCertExtension **extensions, int tag,
|
||||
SECItem *retItem)
|
||||
{
|
||||
SECItem wrapperItem, tmpItem = { siBuffer, 0 };
|
||||
SECStatus rv;
|
||||
PORTCheapArenaPool tmpArena;
|
||||
|
||||
wrapperItem.data = NULL;
|
||||
tmpItem.data = NULL;
|
||||
|
||||
PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
|
||||
|
||||
rv = cert_FindExtension(extensions, tag, &wrapperItem);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &tmpItem,
|
||||
SEC_ASN1_GET(SEC_BitStringTemplate),
|
||||
&wrapperItem);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
retItem->data = (unsigned char *)PORT_Alloc((tmpItem.len + 7) >> 3);
|
||||
if (retItem->data == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
PORT_Memcpy(retItem->data, tmpItem.data, (tmpItem.len + 7) >> 3);
|
||||
retItem->len = tmpItem.len;
|
||||
|
||||
rv = SECSuccess;
|
||||
goto done;
|
||||
|
||||
loser:
|
||||
rv = SECFailure;
|
||||
|
||||
done:
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
|
||||
if (wrapperItem.data) {
|
||||
PORT_Free(wrapperItem.data);
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
PRBool
|
||||
cert_HasCriticalExtension(CERTCertExtension **extensions)
|
||||
{
|
||||
CERTCertExtension **exts;
|
||||
CERTCertExtension *ext = NULL;
|
||||
PRBool hasCriticalExten = PR_FALSE;
|
||||
|
||||
exts = extensions;
|
||||
|
||||
if (exts) {
|
||||
while (*exts) {
|
||||
ext = *exts;
|
||||
/* If the criticality is omitted, it's non-critical */
|
||||
if (ext->critical.data && ext->critical.data[0] == 0xff) {
|
||||
hasCriticalExten = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
exts++;
|
||||
}
|
||||
}
|
||||
return (hasCriticalExten);
|
||||
}
|
||||
|
||||
PRBool
|
||||
cert_HasUnknownCriticalExten(CERTCertExtension **extensions)
|
||||
{
|
||||
CERTCertExtension **exts;
|
||||
CERTCertExtension *ext = NULL;
|
||||
PRBool hasUnknownCriticalExten = PR_FALSE;
|
||||
|
||||
exts = extensions;
|
||||
|
||||
if (exts) {
|
||||
while (*exts) {
|
||||
ext = *exts;
|
||||
/* If the criticality is omitted, it's non-critical.
|
||||
If an extension is critical, make sure that we know
|
||||
how to process the extension.
|
||||
*/
|
||||
if (ext->critical.data && ext->critical.data[0] == 0xff) {
|
||||
if (SECOID_KnownCertExtenOID(&ext->id) == PR_FALSE) {
|
||||
hasUnknownCriticalExten = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
exts++;
|
||||
}
|
||||
}
|
||||
return (hasUnknownCriticalExten);
|
||||
}
|
||||
44
security/nss/lib/certdb/certxutl.h
Normal file
44
security/nss/lib/certdb/certxutl.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* x.509 v3 certificate extension helper routines
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CERTXUTL_H_
|
||||
#define _CERTXUTL_H_
|
||||
|
||||
#include "nspr.h"
|
||||
|
||||
#ifdef OLD
|
||||
typedef enum {
|
||||
CertificateExtensions,
|
||||
CrlExtensions,
|
||||
OCSPRequestExtensions,
|
||||
OCSPSingleRequestExtensions,
|
||||
OCSPResponseSingleExtensions
|
||||
} ExtensionsType;
|
||||
#endif
|
||||
|
||||
extern PRBool cert_HasCriticalExtension(CERTCertExtension **extensions);
|
||||
|
||||
extern SECStatus CERT_FindBitStringExtension(CERTCertExtension **extensions,
|
||||
int tag, SECItem *retItem);
|
||||
extern void *cert_StartExtensions(void *owner, PLArenaPool *arena,
|
||||
void (*setExts)(void *object,
|
||||
CERTCertExtension **exts));
|
||||
|
||||
extern SECStatus cert_FindExtension(CERTCertExtension **extensions, int tag,
|
||||
SECItem *value);
|
||||
|
||||
extern SECStatus cert_FindExtensionByOID(CERTCertExtension **extensions,
|
||||
SECItem *oid, SECItem *value);
|
||||
|
||||
extern SECStatus cert_GetExtenCriticality(CERTCertExtension **extensions,
|
||||
int tag, PRBool *isCritical);
|
||||
|
||||
extern PRBool cert_HasUnknownCriticalExten(CERTCertExtension **extensions);
|
||||
|
||||
#endif
|
||||
15
security/nss/lib/certdb/config.mk
Normal file
15
security/nss/lib/certdb/config.mk
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#
|
||||
# Override TARGETS variable so that only static libraries
|
||||
# are specifed as dependencies within rules.mk.
|
||||
#
|
||||
|
||||
TARGETS = $(LIBRARY)
|
||||
SHARED_LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
3045
security/nss/lib/certdb/crl.c
Normal file
3045
security/nss/lib/certdb/crl.c
Normal file
File diff suppressed because it is too large
Load diff
36
security/nss/lib/certdb/exports.gyp
Normal file
36
security/nss/lib/certdb/exports.gyp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi'
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'lib_certdb_exports',
|
||||
'type': 'none',
|
||||
'copies': [
|
||||
{
|
||||
'files': [
|
||||
'cert.h',
|
||||
'certdb.h',
|
||||
'certt.h'
|
||||
],
|
||||
'destination': '<(nss_public_dist_dir)/<(module)'
|
||||
},
|
||||
{
|
||||
'files': [
|
||||
'certi.h',
|
||||
'certxutl.h',
|
||||
'genname.h',
|
||||
'xconst.h'
|
||||
],
|
||||
'destination': '<(nss_private_dist_dir)/<(module)'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
||||
2019
security/nss/lib/certdb/genname.c
Normal file
2019
security/nss/lib/certdb/genname.c
Normal file
File diff suppressed because it is too large
Load diff
93
security/nss/lib/certdb/genname.h
Normal file
93
security/nss/lib/certdb/genname.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _GENAME_H_
|
||||
#define _GENAME_H_
|
||||
|
||||
#include "plarena.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "secasn1.h"
|
||||
#include "secder.h"
|
||||
#include "certt.h"
|
||||
|
||||
/************************************************************************/
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
extern const SEC_ASN1Template CERT_GeneralNamesTemplate[];
|
||||
|
||||
extern SECItem **cert_EncodeGeneralNames(PLArenaPool *arena,
|
||||
CERTGeneralName *names);
|
||||
|
||||
extern CERTGeneralName *cert_DecodeGeneralNames(PLArenaPool *arena,
|
||||
SECItem **encodedGenName);
|
||||
|
||||
extern SECStatus cert_DestroyGeneralNames(CERTGeneralName *name);
|
||||
|
||||
extern SECStatus cert_EncodeNameConstraints(CERTNameConstraints *constraints,
|
||||
PLArenaPool *arena, SECItem *dest);
|
||||
|
||||
extern CERTNameConstraints *cert_DecodeNameConstraints(
|
||||
PLArenaPool *arena, const SECItem *encodedConstraints);
|
||||
|
||||
extern CERTGeneralName *cert_CombineNamesLists(CERTGeneralName *list1,
|
||||
CERTGeneralName *list2);
|
||||
|
||||
extern CERTNameConstraint *cert_CombineConstraintsLists(
|
||||
CERTNameConstraint *list1, CERTNameConstraint *list2);
|
||||
|
||||
/*********************************************************************/
|
||||
/* A thread safe implementation of General Names */
|
||||
/*********************************************************************/
|
||||
|
||||
/* Destroy a Single CERTGeneralName */
|
||||
void CERT_DestroyGeneralName(CERTGeneralName *name);
|
||||
|
||||
SECStatus CERT_CompareGeneralName(CERTGeneralName *a, CERTGeneralName *b);
|
||||
|
||||
SECStatus CERT_CopyGeneralName(PLArenaPool *arena, CERTGeneralName *dest,
|
||||
CERTGeneralName *src);
|
||||
|
||||
/* General Name Lists are a thread safe, reference counting layer to
|
||||
* general names */
|
||||
|
||||
/* Destroys a CERTGeneralNameList */
|
||||
void CERT_DestroyGeneralNameList(CERTGeneralNameList *list);
|
||||
|
||||
/* Creates a CERTGeneralNameList */
|
||||
CERTGeneralNameList *CERT_CreateGeneralNameList(CERTGeneralName *name);
|
||||
|
||||
/* Compares two CERTGeneralNameList */
|
||||
SECStatus CERT_CompareGeneralNameLists(CERTGeneralNameList *a,
|
||||
CERTGeneralNameList *b);
|
||||
|
||||
/* returns a copy of the first name of the type requested */
|
||||
void *CERT_GetGeneralNameFromListByType(CERTGeneralNameList *list,
|
||||
CERTGeneralNameType type,
|
||||
PLArenaPool *arena);
|
||||
|
||||
/* Adds a name to the tail of the list */
|
||||
void CERT_AddGeneralNameToList(CERTGeneralNameList *list,
|
||||
CERTGeneralNameType type, void *data,
|
||||
SECItem *oid);
|
||||
|
||||
/* returns a duplicate of the CERTGeneralNameList */
|
||||
CERTGeneralNameList *CERT_DupGeneralNameList(CERTGeneralNameList *list);
|
||||
|
||||
/* returns the number of CERTGeneralName objects in the doubly linked
|
||||
** list of which *names is a member.
|
||||
*/
|
||||
extern int CERT_GetNamesLength(CERTGeneralName *names);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
SECStatus CERT_CompareNameSpace(CERTCertificate *cert,
|
||||
CERTGeneralName *namesList,
|
||||
CERTCertificate **certsList,
|
||||
PLArenaPool *reqArena,
|
||||
CERTCertificate **pBadCert);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
40
security/nss/lib/certdb/manifest.mn
Normal file
40
security/nss/lib/certdb/manifest.mn
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
CORE_DEPTH = ../..
|
||||
|
||||
EXPORTS = \
|
||||
cert.h \
|
||||
certt.h \
|
||||
certdb.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
genname.h \
|
||||
xconst.h \
|
||||
certxutl.h \
|
||||
certi.h \
|
||||
$(NULL)
|
||||
|
||||
MODULE = nss
|
||||
|
||||
CSRCS = \
|
||||
alg1485.c \
|
||||
certdb.c \
|
||||
certv3.c \
|
||||
certxutl.c \
|
||||
crl.c \
|
||||
genname.c \
|
||||
stanpcertdb.c \
|
||||
polcyxtn.c \
|
||||
secname.c \
|
||||
xauthkid.c \
|
||||
xbsconst.c \
|
||||
xconst.c \
|
||||
$(NULL)
|
||||
|
||||
LIBRARY_NAME = certdb
|
||||
|
||||
# This part of the code, including all sub-dirs, can be optimized for size
|
||||
export ALLOW_OPT_CODE_SIZE = 1
|
||||
806
security/nss/lib/certdb/polcyxtn.c
Normal file
806
security/nss/lib/certdb/polcyxtn.c
Normal file
|
|
@ -0,0 +1,806 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Support for various policy related extensions
|
||||
*/
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "secport.h"
|
||||
#include "secder.h"
|
||||
#include "cert.h"
|
||||
#include "secoid.h"
|
||||
#include "secasn1.h"
|
||||
#include "secerr.h"
|
||||
#include "nspr.h"
|
||||
|
||||
SEC_ASN1_MKSUB(SEC_IntegerTemplate)
|
||||
SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
|
||||
|
||||
const SEC_ASN1Template CERT_DisplayTextTypeTemplate[] = {
|
||||
{ SEC_ASN1_CHOICE, offsetof(SECItem, type), 0, sizeof(SECItem) },
|
||||
{ SEC_ASN1_IA5_STRING, 0, 0, siAsciiString },
|
||||
{ SEC_ASN1_VISIBLE_STRING, 0, 0, siVisibleString },
|
||||
{ SEC_ASN1_BMP_STRING, 0, 0, siBMPString },
|
||||
{ SEC_ASN1_UTF8_STRING, 0, 0, siUTF8String },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_NoticeReferenceTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNoticeReference) },
|
||||
{ SEC_ASN1_INLINE, offsetof(CERTNoticeReference, organization),
|
||||
CERT_DisplayTextTypeTemplate, 0 },
|
||||
{ SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN,
|
||||
offsetof(CERTNoticeReference, noticeNumbers),
|
||||
SEC_ASN1_SUB(SEC_IntegerTemplate) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_UserNoticeTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTUserNotice) },
|
||||
{ SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
|
||||
offsetof(CERTUserNotice, noticeReference), CERT_NoticeReferenceTemplate,
|
||||
0 },
|
||||
{ SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
|
||||
offsetof(CERTUserNotice, displayText), CERT_DisplayTextTypeTemplate, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_PolicyQualifierTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyQualifier) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyQualifier, qualifierID) },
|
||||
{ SEC_ASN1_ANY, offsetof(CERTPolicyQualifier, qualifierValue) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_PolicyInfoTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyInfo) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyInfo, policyID) },
|
||||
{ SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
|
||||
offsetof(CERTPolicyInfo, policyQualifiers),
|
||||
CERT_PolicyQualifierTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_CertificatePoliciesTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE_OF, offsetof(CERTCertificatePolicies, policyInfos),
|
||||
CERT_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_PolicyMapTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyMap) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyMap, issuerDomainPolicy) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyMap, subjectDomainPolicy) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_PolicyMappingsTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE_OF, offsetof(CERTCertificatePolicyMappings, policyMaps),
|
||||
CERT_PolicyMapTemplate, sizeof(CERTPolicyMap) }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_PolicyConstraintsTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCertificatePolicyConstraints) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
|
||||
offsetof(CERTCertificatePolicyConstraints, explicitPolicySkipCerts),
|
||||
SEC_ASN1_SUB(SEC_IntegerTemplate) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
|
||||
offsetof(CERTCertificatePolicyConstraints, inhibitMappingSkipCerts),
|
||||
SEC_ASN1_SUB(SEC_IntegerTemplate) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_InhibitAnyTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER,
|
||||
offsetof(CERTCertificateInhibitAny, inhibitAnySkipCerts), NULL,
|
||||
sizeof(CERTCertificateInhibitAny) }
|
||||
};
|
||||
|
||||
static void
|
||||
breakLines(char *string)
|
||||
{
|
||||
char *tmpstr;
|
||||
char *lastspace = NULL;
|
||||
int curlen = 0;
|
||||
int c;
|
||||
|
||||
tmpstr = string;
|
||||
|
||||
while ((c = *tmpstr) != '\0') {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
lastspace = tmpstr;
|
||||
break;
|
||||
case '\n':
|
||||
lastspace = NULL;
|
||||
curlen = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((curlen >= 55) && (lastspace != NULL)) {
|
||||
*lastspace = '\n';
|
||||
curlen = (tmpstr - lastspace);
|
||||
lastspace = NULL;
|
||||
}
|
||||
|
||||
curlen++;
|
||||
tmpstr++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CERTCertificatePolicies *
|
||||
CERT_DecodeCertificatePoliciesExtension(const SECItem *extnValue)
|
||||
{
|
||||
PLArenaPool *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 certificate policies structure */
|
||||
policies = (CERTCertificatePolicies *)PORT_ArenaZAlloc(
|
||||
arena, sizeof(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, CERT_CertificatePoliciesTemplate, &newExtnValue);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* initialize the oid tags */
|
||||
policyInfos = policies->policyInfos;
|
||||
while (*policyInfos != NULL) {
|
||||
policyInfo = *policyInfos;
|
||||
policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
|
||||
policyQualifiers = policyInfo->policyQualifiers;
|
||||
while (policyQualifiers != NULL && *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);
|
||||
}
|
||||
|
||||
void
|
||||
CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies)
|
||||
{
|
||||
if (policies != NULL) {
|
||||
PORT_FreeArena(policies->arena, PR_FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings *mappings)
|
||||
{
|
||||
if (mappings != NULL) {
|
||||
PORT_FreeArena(mappings->arena, PR_FALSE);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
CERT_DestroyUserNotice(CERTUserNotice *userNotice)
|
||||
{
|
||||
if (userNotice != NULL) {
|
||||
PORT_FreeArena(userNotice->arena, PR_FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static CERTPolicyStringCallback policyStringCB = NULL;
|
||||
static void *policyStringCBArg = NULL;
|
||||
|
||||
void
|
||||
CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg)
|
||||
{
|
||||
policyStringCB = cb;
|
||||
policyStringCBArg = cbarg;
|
||||
return;
|
||||
}
|
||||
|
||||
char *
|
||||
stringFromUserNotice(SECItem *noticeItem)
|
||||
{
|
||||
SECItem *org;
|
||||
unsigned int len, headerlen;
|
||||
char *stringbuf;
|
||||
CERTUserNotice *userNotice;
|
||||
char *policystr;
|
||||
char *retstr = NULL;
|
||||
SECItem *displayText;
|
||||
SECItem **noticeNumbers;
|
||||
unsigned int strnum;
|
||||
|
||||
/* decode the user notice */
|
||||
userNotice = CERT_DecodeUserNotice(noticeItem);
|
||||
if (userNotice == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
org = &userNotice->noticeReference.organization;
|
||||
if ((org->len != 0) && (policyStringCB != NULL)) {
|
||||
/* has a noticeReference */
|
||||
|
||||
/* extract the org string */
|
||||
len = org->len;
|
||||
stringbuf = (char *)PORT_Alloc(len + 1);
|
||||
if (stringbuf != NULL) {
|
||||
PORT_Memcpy(stringbuf, org->data, len);
|
||||
stringbuf[len] = '\0';
|
||||
|
||||
noticeNumbers = userNotice->noticeReference.noticeNumbers;
|
||||
while (*noticeNumbers != NULL) {
|
||||
/* XXX - only one byte integers right now*/
|
||||
strnum = (*noticeNumbers)->data[0];
|
||||
policystr =
|
||||
(*policyStringCB)(stringbuf, strnum, policyStringCBArg);
|
||||
if (policystr != NULL) {
|
||||
if (retstr != NULL) {
|
||||
retstr = PR_sprintf_append(retstr, "\n%s", policystr);
|
||||
} else {
|
||||
retstr = PR_sprintf_append(retstr, "%s", policystr);
|
||||
}
|
||||
|
||||
PORT_Free(policystr);
|
||||
}
|
||||
|
||||
noticeNumbers++;
|
||||
}
|
||||
|
||||
PORT_Free(stringbuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (retstr == NULL) {
|
||||
if (userNotice->displayText.len != 0) {
|
||||
displayText = &userNotice->displayText;
|
||||
|
||||
if (displayText->len > 2) {
|
||||
if (displayText->data[0] == SEC_ASN1_VISIBLE_STRING) {
|
||||
headerlen = 2;
|
||||
if (displayText->data[1] & 0x80) {
|
||||
/* multibyte length */
|
||||
headerlen += (displayText->data[1] & 0x7f);
|
||||
}
|
||||
|
||||
len = displayText->len - headerlen;
|
||||
retstr = (char *)PORT_Alloc(len + 1);
|
||||
if (retstr != NULL) {
|
||||
PORT_Memcpy(retstr, &displayText->data[headerlen], len);
|
||||
retstr[len] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CERT_DestroyUserNotice(userNotice);
|
||||
|
||||
return (retstr);
|
||||
}
|
||||
|
||||
char *
|
||||
CERT_GetCertCommentString(CERTCertificate *cert)
|
||||
{
|
||||
char *retstring = NULL;
|
||||
SECStatus rv;
|
||||
SECItem policyItem;
|
||||
CERTCertificatePolicies *policies = NULL;
|
||||
CERTPolicyInfo **policyInfos;
|
||||
CERTPolicyQualifier **policyQualifiers, *qualifier;
|
||||
|
||||
policyItem.data = NULL;
|
||||
|
||||
rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES,
|
||||
&policyItem);
|
||||
if (rv != SECSuccess) {
|
||||
goto nopolicy;
|
||||
}
|
||||
|
||||
policies = CERT_DecodeCertificatePoliciesExtension(&policyItem);
|
||||
if (policies == NULL) {
|
||||
goto nopolicy;
|
||||
}
|
||||
|
||||
policyInfos = policies->policyInfos;
|
||||
/* search through policyInfos looking for the verisign policy */
|
||||
while (*policyInfos != NULL) {
|
||||
if ((*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES) {
|
||||
policyQualifiers = (*policyInfos)->policyQualifiers;
|
||||
/* search through the policy qualifiers looking for user notice */
|
||||
while (policyQualifiers != NULL && *policyQualifiers != NULL) {
|
||||
qualifier = *policyQualifiers;
|
||||
if (qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER) {
|
||||
retstring =
|
||||
stringFromUserNotice(&qualifier->qualifierValue);
|
||||
break;
|
||||
}
|
||||
|
||||
policyQualifiers++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
policyInfos++;
|
||||
}
|
||||
|
||||
nopolicy:
|
||||
if (policyItem.data != NULL) {
|
||||
PORT_Free(policyItem.data);
|
||||
}
|
||||
|
||||
if (policies != NULL) {
|
||||
CERT_DestroyCertificatePoliciesExtension(policies);
|
||||
}
|
||||
|
||||
if (retstring == NULL) {
|
||||
retstring =
|
||||
CERT_FindNSStringExtension(cert, SEC_OID_NS_CERT_EXT_COMMENT);
|
||||
}
|
||||
|
||||
if (retstring != NULL) {
|
||||
breakLines(retstring);
|
||||
}
|
||||
|
||||
return (retstring);
|
||||
}
|
||||
|
||||
const SEC_ASN1Template CERT_OidSeqTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids),
|
||||
SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
CERT_DestroyOidSequence(CERTOidSequence *oidSeq)
|
||||
{
|
||||
if (oidSeq != NULL) {
|
||||
PORT_FreeArena(oidSeq->arena, PR_FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
PRBool
|
||||
CERT_GovtApprovedBitSet(CERTCertificate *cert)
|
||||
{
|
||||
SECStatus rv;
|
||||
SECItem extItem;
|
||||
CERTOidSequence *oidSeq = NULL;
|
||||
PRBool ret;
|
||||
SECItem **oids;
|
||||
SECItem *oid;
|
||||
SECOidTag oidTag;
|
||||
|
||||
extItem.data = NULL;
|
||||
rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
oidSeq = CERT_DecodeOidSequence(&extItem);
|
||||
if (oidSeq == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
oids = oidSeq->oids;
|
||||
while (oids != NULL && *oids != NULL) {
|
||||
oid = *oids;
|
||||
|
||||
oidTag = SECOID_FindOIDTag(oid);
|
||||
|
||||
if (oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) {
|
||||
goto success;
|
||||
}
|
||||
|
||||
oids++;
|
||||
}
|
||||
|
||||
loser:
|
||||
ret = PR_FALSE;
|
||||
goto done;
|
||||
success:
|
||||
ret = PR_TRUE;
|
||||
done:
|
||||
if (oidSeq != NULL) {
|
||||
CERT_DestroyOidSequence(oidSeq);
|
||||
}
|
||||
if (extItem.data != NULL) {
|
||||
PORT_Free(extItem.data);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodePolicyConstraintsExtension(PLArenaPool *arena,
|
||||
CERTCertificatePolicyConstraints *constr,
|
||||
SECItem *dest)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
PORT_Assert(constr != NULL && dest != NULL);
|
||||
if (constr == NULL || dest == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (SEC_ASN1EncodeItem(arena, dest, constr,
|
||||
CERT_PolicyConstraintsTemplate) == NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodePolicyMappingExtension(PLArenaPool *arena,
|
||||
CERTCertificatePolicyMappings *mapping,
|
||||
SECItem *dest)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
PORT_Assert(mapping != NULL && dest != NULL);
|
||||
if (mapping == NULL || dest == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (SEC_ASN1EncodeItem(arena, dest, mapping, CERT_PolicyMappingsTemplate) ==
|
||||
NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeCertPoliciesExtension(PLArenaPool *arena, CERTPolicyInfo **info,
|
||||
SECItem *dest)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
PORT_Assert(info != NULL && dest != NULL);
|
||||
if (info == NULL || dest == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (SEC_ASN1EncodeItem(arena, dest, info,
|
||||
CERT_CertificatePoliciesTemplate) == NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeUserNotice(PLArenaPool *arena, CERTUserNotice *notice, SECItem *dest)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
PORT_Assert(notice != NULL && dest != NULL);
|
||||
if (notice == NULL || dest == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (SEC_ASN1EncodeItem(arena, dest, notice, CERT_UserNoticeTemplate) ==
|
||||
NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeNoticeReference(PLArenaPool *arena, CERTNoticeReference *reference,
|
||||
SECItem *dest)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
PORT_Assert(reference != NULL && dest != NULL);
|
||||
if (reference == NULL || dest == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (SEC_ASN1EncodeItem(arena, dest, reference,
|
||||
CERT_NoticeReferenceTemplate) == NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeInhibitAnyExtension(PLArenaPool *arena,
|
||||
CERTCertificateInhibitAny *certInhibitAny,
|
||||
SECItem *dest)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
PORT_Assert(certInhibitAny != NULL && dest != NULL);
|
||||
if (certInhibitAny == NULL || dest == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (SEC_ASN1EncodeItem(arena, dest, certInhibitAny,
|
||||
CERT_InhibitAnyTemplate) == NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
711
security/nss/lib/certdb/secname.c
Normal file
711
security/nss/lib/certdb/secname.c
Normal file
|
|
@ -0,0 +1,711 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "cert.h"
|
||||
#include "secoid.h"
|
||||
#include "secder.h" /* XXX remove this when remove the DERTemplates */
|
||||
#include "secasn1.h"
|
||||
#include "secitem.h"
|
||||
#include <stdarg.h>
|
||||
#include "secerr.h"
|
||||
#include "certi.h"
|
||||
|
||||
static const SEC_ASN1Template cert_AVATemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTAVA) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(CERTAVA, type) },
|
||||
{ SEC_ASN1_ANY, offsetof(CERTAVA, value) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERT_RDNTemplate[] = {
|
||||
{ SEC_ASN1_SET_OF, offsetof(CERTRDN, avas), cert_AVATemplate,
|
||||
sizeof(CERTRDN) }
|
||||
};
|
||||
|
||||
static int
|
||||
CountArray(void **array)
|
||||
{
|
||||
int count = 0;
|
||||
if (array) {
|
||||
while (*array++) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void **
|
||||
AddToArray(PLArenaPool *arena, void **array, void *element)
|
||||
{
|
||||
unsigned count;
|
||||
void **ap;
|
||||
|
||||
/* Count up number of slots already in use in the array */
|
||||
count = 0;
|
||||
ap = array;
|
||||
if (ap) {
|
||||
while (*ap++) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (array) {
|
||||
array =
|
||||
(void **)PORT_ArenaGrow(arena, array, (count + 1) * sizeof(void *),
|
||||
(count + 2) * sizeof(void *));
|
||||
} else {
|
||||
array = (void **)PORT_ArenaAlloc(arena, (count + 2) * sizeof(void *));
|
||||
}
|
||||
if (array) {
|
||||
array[count] = element;
|
||||
array[count + 1] = 0;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
SECOidTag
|
||||
CERT_GetAVATag(CERTAVA *ava)
|
||||
{
|
||||
SECOidData *oid;
|
||||
if (!ava->type.data)
|
||||
return (SECOidTag)-1;
|
||||
|
||||
oid = SECOID_FindOID(&ava->type);
|
||||
|
||||
if (oid) {
|
||||
return (oid->offset);
|
||||
}
|
||||
return (SECOidTag)-1;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
SetupAVAType(PLArenaPool *arena, SECOidTag type, SECItem *it, unsigned *maxLenp)
|
||||
{
|
||||
unsigned char *oid;
|
||||
unsigned oidLen;
|
||||
unsigned char *cp;
|
||||
int maxLen;
|
||||
SECOidData *oidrec;
|
||||
|
||||
oidrec = SECOID_FindOIDByTag(type);
|
||||
if (oidrec == NULL)
|
||||
return SECFailure;
|
||||
|
||||
oid = oidrec->oid.data;
|
||||
oidLen = oidrec->oid.len;
|
||||
|
||||
maxLen = cert_AVAOidTagToMaxLen(type);
|
||||
if (maxLen < 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
it->data = cp = (unsigned char *)PORT_ArenaAlloc(arena, oidLen);
|
||||
if (cp == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
it->len = oidLen;
|
||||
PORT_Memcpy(cp, oid, oidLen);
|
||||
*maxLenp = (unsigned)maxLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
SetupAVAValue(PLArenaPool *arena, int valueType, const SECItem *in,
|
||||
SECItem *out, unsigned maxLen)
|
||||
{
|
||||
PRUint8 *value, *cp, *ucs4Val;
|
||||
unsigned valueLen, valueLenLen, total;
|
||||
unsigned ucs4Len = 0, ucs4MaxLen;
|
||||
|
||||
value = in->data;
|
||||
valueLen = in->len;
|
||||
switch (valueType) {
|
||||
case SEC_ASN1_PRINTABLE_STRING:
|
||||
case SEC_ASN1_IA5_STRING:
|
||||
case SEC_ASN1_T61_STRING:
|
||||
case SEC_ASN1_UTF8_STRING: /* no conversion required */
|
||||
break;
|
||||
case SEC_ASN1_UNIVERSAL_STRING:
|
||||
ucs4MaxLen = valueLen * 6;
|
||||
ucs4Val = (PRUint8 *)PORT_ArenaZAlloc(arena, ucs4MaxLen);
|
||||
if (!ucs4Val ||
|
||||
!PORT_UCS4_UTF8Conversion(PR_TRUE, value, valueLen, ucs4Val,
|
||||
ucs4MaxLen, &ucs4Len)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
value = ucs4Val;
|
||||
valueLen = ucs4Len;
|
||||
maxLen *= 4;
|
||||
break;
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (valueLen > maxLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
valueLenLen = DER_LengthLength(valueLen);
|
||||
total = 1 + valueLenLen + valueLen;
|
||||
cp = (PRUint8 *)PORT_ArenaAlloc(arena, total);
|
||||
if (!cp) {
|
||||
return SECFailure;
|
||||
}
|
||||
out->data = cp;
|
||||
out->len = total;
|
||||
cp = (PRUint8 *)DER_StoreHeader(cp, valueType, valueLen);
|
||||
PORT_Memcpy(cp, value, valueLen);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
CERTAVA *
|
||||
CERT_CreateAVAFromRaw(PLArenaPool *pool, const SECItem *OID,
|
||||
const SECItem *value)
|
||||
{
|
||||
CERTAVA *ava;
|
||||
int rv;
|
||||
|
||||
ava = PORT_ArenaZNew(pool, CERTAVA);
|
||||
if (ava) {
|
||||
rv = SECITEM_CopyItem(pool, &ava->type, OID);
|
||||
if (rv)
|
||||
return NULL;
|
||||
|
||||
rv = SECITEM_CopyItem(pool, &ava->value, value);
|
||||
if (rv)
|
||||
return NULL;
|
||||
}
|
||||
return ava;
|
||||
}
|
||||
|
||||
CERTAVA *
|
||||
CERT_CreateAVAFromSECItem(PLArenaPool *arena, SECOidTag kind, int valueType,
|
||||
SECItem *value)
|
||||
{
|
||||
CERTAVA *ava;
|
||||
int rv;
|
||||
unsigned maxLen;
|
||||
|
||||
ava = (CERTAVA *)PORT_ArenaZAlloc(arena, sizeof(CERTAVA));
|
||||
if (ava) {
|
||||
rv = SetupAVAType(arena, kind, &ava->type, &maxLen);
|
||||
if (rv) {
|
||||
/* Illegal AVA type */
|
||||
return NULL;
|
||||
}
|
||||
rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen);
|
||||
if (rv) {
|
||||
/* Illegal value type */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return ava;
|
||||
}
|
||||
|
||||
CERTAVA *
|
||||
CERT_CreateAVA(PLArenaPool *arena, SECOidTag kind, int valueType, char *value)
|
||||
{
|
||||
SECItem item = { siBuffer, NULL, 0 };
|
||||
|
||||
item.data = (PRUint8 *)value;
|
||||
item.len = PORT_Strlen(value);
|
||||
|
||||
return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item);
|
||||
}
|
||||
|
||||
CERTAVA *
|
||||
CERT_CopyAVA(PLArenaPool *arena, CERTAVA *from)
|
||||
{
|
||||
CERTAVA *ava;
|
||||
int rv;
|
||||
|
||||
ava = (CERTAVA *)PORT_ArenaZAlloc(arena, sizeof(CERTAVA));
|
||||
if (ava) {
|
||||
rv = SECITEM_CopyItem(arena, &ava->type, &from->type);
|
||||
if (rv)
|
||||
goto loser;
|
||||
rv = SECITEM_CopyItem(arena, &ava->value, &from->value);
|
||||
if (rv)
|
||||
goto loser;
|
||||
}
|
||||
return ava;
|
||||
|
||||
loser:
|
||||
return 0;
|
||||
}
|
||||
|
||||
CERTRDN *
|
||||
CERT_CreateRDN(PLArenaPool *arena, CERTAVA *ava0, ...)
|
||||
{
|
||||
CERTAVA *ava;
|
||||
CERTRDN *rdn;
|
||||
va_list ap;
|
||||
unsigned count;
|
||||
CERTAVA **avap;
|
||||
|
||||
rdn = (CERTRDN *)PORT_ArenaAlloc(arena, sizeof(CERTRDN));
|
||||
if (rdn) {
|
||||
/* Count number of avas going into the rdn */
|
||||
count = 0;
|
||||
if (ava0) {
|
||||
count++;
|
||||
va_start(ap, ava0);
|
||||
while ((ava = va_arg(ap, CERTAVA *)) != 0) {
|
||||
count++;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Now fill in the pointers */
|
||||
rdn->avas = avap =
|
||||
(CERTAVA **)PORT_ArenaAlloc(arena, (count + 1) * sizeof(CERTAVA *));
|
||||
if (!avap) {
|
||||
return 0;
|
||||
}
|
||||
if (ava0) {
|
||||
*avap++ = ava0;
|
||||
va_start(ap, ava0);
|
||||
while ((ava = va_arg(ap, CERTAVA *)) != 0) {
|
||||
*avap++ = ava;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
*avap++ = 0;
|
||||
}
|
||||
return rdn;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_AddAVA(PLArenaPool *arena, CERTRDN *rdn, CERTAVA *ava)
|
||||
{
|
||||
rdn->avas = (CERTAVA **)AddToArray(arena, (void **)rdn->avas, ava);
|
||||
return rdn->avas ? SECSuccess : SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_CopyRDN(PLArenaPool *arena, CERTRDN *to, CERTRDN *from)
|
||||
{
|
||||
CERTAVA **avas, *fava, *tava;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
/* Copy each ava from from */
|
||||
avas = from->avas;
|
||||
if (avas) {
|
||||
if (avas[0] == NULL) {
|
||||
rv = CERT_AddAVA(arena, to, NULL);
|
||||
return rv;
|
||||
}
|
||||
while ((fava = *avas++) != 0) {
|
||||
tava = CERT_CopyAVA(arena, fava);
|
||||
if (!tava) {
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
rv = CERT_AddAVA(arena, to, tava);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
const SEC_ASN1Template CERT_NameTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE_OF, offsetof(CERTName, rdns), CERT_RDNTemplate,
|
||||
sizeof(CERTName) }
|
||||
};
|
||||
|
||||
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_NameTemplate)
|
||||
|
||||
CERTName *
|
||||
CERT_CreateName(CERTRDN *rdn0, ...)
|
||||
{
|
||||
CERTRDN *rdn;
|
||||
CERTName *name;
|
||||
va_list ap;
|
||||
unsigned count;
|
||||
CERTRDN **rdnp;
|
||||
PLArenaPool *arena;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
name = (CERTName *)PORT_ArenaAlloc(arena, sizeof(CERTName));
|
||||
if (name) {
|
||||
name->arena = arena;
|
||||
|
||||
/* Count number of RDNs going into the Name */
|
||||
if (!rdn0) {
|
||||
count = 0;
|
||||
} else {
|
||||
count = 1;
|
||||
va_start(ap, rdn0);
|
||||
while ((rdn = va_arg(ap, CERTRDN *)) != 0) {
|
||||
count++;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Allocate space (including space for terminal null ptr) */
|
||||
name->rdns = rdnp =
|
||||
(CERTRDN **)PORT_ArenaAlloc(arena, (count + 1) * sizeof(CERTRDN *));
|
||||
if (!name->rdns) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Now fill in the pointers */
|
||||
if (count > 0) {
|
||||
*rdnp++ = rdn0;
|
||||
va_start(ap, rdn0);
|
||||
while ((rdn = va_arg(ap, CERTRDN *)) != 0) {
|
||||
*rdnp++ = rdn;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* null terminate the list */
|
||||
*rdnp++ = 0;
|
||||
}
|
||||
return name;
|
||||
|
||||
loser:
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
CERT_DestroyName(CERTName *name)
|
||||
{
|
||||
if (name) {
|
||||
PLArenaPool *arena = name->arena;
|
||||
name->rdns = NULL;
|
||||
name->arena = NULL;
|
||||
if (arena)
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_AddRDN(CERTName *name, CERTRDN *rdn)
|
||||
{
|
||||
name->rdns = (CERTRDN **)AddToArray(name->arena, (void **)name->rdns, rdn);
|
||||
return name->rdns ? SECSuccess : SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_CopyName(PLArenaPool *arena, CERTName *to, const CERTName *from)
|
||||
{
|
||||
CERTRDN **rdns, *frdn, *trdn;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
if (!to || !from) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
CERT_DestroyName(to);
|
||||
to->arena = arena;
|
||||
|
||||
/* Copy each rdn from from */
|
||||
rdns = from->rdns;
|
||||
if (rdns) {
|
||||
if (rdns[0] == NULL) {
|
||||
rv = CERT_AddRDN(to, NULL);
|
||||
return rv;
|
||||
}
|
||||
while ((frdn = *rdns++) != NULL) {
|
||||
trdn = CERT_CreateRDN(arena, NULL);
|
||||
if (!trdn) {
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
rv = CERT_CopyRDN(arena, trdn, frdn);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
rv = CERT_AddRDN(to, trdn);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
static void
|
||||
canonicalize(SECItem *foo)
|
||||
{
|
||||
int ch, lastch, len, src, dest;
|
||||
|
||||
/* strip trailing whitespace. */
|
||||
len = foo->len;
|
||||
while (len > 0 && ((ch = foo->data[len - 1]) == ' ' || ch == '\t' ||
|
||||
ch == '\r' || ch == '\n')) {
|
||||
len--;
|
||||
}
|
||||
|
||||
src = 0;
|
||||
/* strip leading whitespace. */
|
||||
while (src < len && ((ch = foo->data[src]) == ' ' || ch == '\t' ||
|
||||
ch == '\r' || ch == '\n')) {
|
||||
src++;
|
||||
}
|
||||
dest = 0;
|
||||
lastch = ' ';
|
||||
while (src < len) {
|
||||
ch = foo->data[src++];
|
||||
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
|
||||
ch = ' ';
|
||||
if (ch == lastch)
|
||||
continue;
|
||||
} else if (ch >= 'A' && ch <= 'Z') {
|
||||
ch |= 0x20; /* downshift */
|
||||
}
|
||||
foo->data[dest++] = lastch = ch;
|
||||
}
|
||||
foo->len = dest;
|
||||
}
|
||||
|
||||
/* SECItems a and b contain DER-encoded printable strings. */
|
||||
SECComparison
|
||||
CERT_CompareDERPrintableStrings(const SECItem *a, const SECItem *b)
|
||||
{
|
||||
SECComparison rv = SECLessThan;
|
||||
SECItem *aVal = CERT_DecodeAVAValue(a);
|
||||
SECItem *bVal = CERT_DecodeAVAValue(b);
|
||||
|
||||
if (aVal && aVal->len && aVal->data && bVal && bVal->len && bVal->data) {
|
||||
canonicalize(aVal);
|
||||
canonicalize(bVal);
|
||||
rv = SECITEM_CompareItem(aVal, bVal);
|
||||
}
|
||||
SECITEM_FreeItem(aVal, PR_TRUE);
|
||||
SECITEM_FreeItem(bVal, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECComparison
|
||||
CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b)
|
||||
{
|
||||
SECComparison rv;
|
||||
|
||||
rv = SECITEM_CompareItem(&a->type, &b->type);
|
||||
if (SECEqual != rv)
|
||||
return rv; /* Attribute types don't match. */
|
||||
/* Let's be optimistic. Maybe the values will just compare equal. */
|
||||
rv = SECITEM_CompareItem(&a->value, &b->value);
|
||||
if (SECEqual == rv)
|
||||
return rv; /* values compared exactly. */
|
||||
if (a->value.len && a->value.data && b->value.len && b->value.data) {
|
||||
/* Here, the values did not match.
|
||||
** If the values had different encodings, convert them to the same
|
||||
** encoding and compare that way.
|
||||
*/
|
||||
if (a->value.data[0] != b->value.data[0]) {
|
||||
/* encodings differ. Convert both to UTF-8 and compare. */
|
||||
SECItem *aVal = CERT_DecodeAVAValue(&a->value);
|
||||
SECItem *bVal = CERT_DecodeAVAValue(&b->value);
|
||||
if (aVal && aVal->len && aVal->data && bVal && bVal->len &&
|
||||
bVal->data) {
|
||||
rv = SECITEM_CompareItem(aVal, bVal);
|
||||
}
|
||||
SECITEM_FreeItem(aVal, PR_TRUE);
|
||||
SECITEM_FreeItem(bVal, PR_TRUE);
|
||||
} else if (a->value.data[0] == 0x13) { /* both are printable strings. */
|
||||
/* printable strings */
|
||||
rv = CERT_CompareDERPrintableStrings(&a->value, &b->value);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECComparison
|
||||
CERT_CompareRDN(const CERTRDN *a, const CERTRDN *b)
|
||||
{
|
||||
CERTAVA **aavas, *aava;
|
||||
CERTAVA **bavas, *bava;
|
||||
int ac, bc;
|
||||
SECComparison rv = SECEqual;
|
||||
|
||||
aavas = a->avas;
|
||||
bavas = b->avas;
|
||||
|
||||
/*
|
||||
** Make sure array of ava's are the same length. If not, then we are
|
||||
** not equal
|
||||
*/
|
||||
ac = CountArray((void **)aavas);
|
||||
bc = CountArray((void **)bavas);
|
||||
if (ac < bc)
|
||||
return SECLessThan;
|
||||
if (ac > bc)
|
||||
return SECGreaterThan;
|
||||
|
||||
while (NULL != (aava = *aavas++)) {
|
||||
for (bavas = b->avas; NULL != (bava = *bavas++);) {
|
||||
rv = SECITEM_CompareItem(&aava->type, &bava->type);
|
||||
if (SECEqual == rv) {
|
||||
rv = CERT_CompareAVA(aava, bava);
|
||||
if (SECEqual != rv)
|
||||
return rv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bava) /* didn't find a match */
|
||||
return SECGreaterThan;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECComparison
|
||||
CERT_CompareName(const CERTName *a, const CERTName *b)
|
||||
{
|
||||
CERTRDN **ardns, *ardn;
|
||||
CERTRDN **brdns, *brdn;
|
||||
int ac, bc;
|
||||
SECComparison rv = SECEqual;
|
||||
|
||||
ardns = a->rdns;
|
||||
brdns = b->rdns;
|
||||
|
||||
/*
|
||||
** Make sure array of rdn's are the same length. If not, then we are
|
||||
** not equal
|
||||
*/
|
||||
ac = CountArray((void **)ardns);
|
||||
bc = CountArray((void **)brdns);
|
||||
if (ac < bc)
|
||||
return SECLessThan;
|
||||
if (ac > bc)
|
||||
return SECGreaterThan;
|
||||
|
||||
for (;;) {
|
||||
if (!ardns++ || !brdns++) {
|
||||
break;
|
||||
}
|
||||
ardn = *ardns;
|
||||
brdn = *brdns;
|
||||
if (!ardn) {
|
||||
break;
|
||||
}
|
||||
rv = CERT_CompareRDN(ardn, brdn);
|
||||
if (rv)
|
||||
return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Moved from certhtml.c */
|
||||
SECItem *
|
||||
CERT_DecodeAVAValue(const SECItem *derAVAValue)
|
||||
{
|
||||
SECItem *retItem;
|
||||
const SEC_ASN1Template *theTemplate = NULL;
|
||||
enum { conv_none,
|
||||
conv_ucs4,
|
||||
conv_ucs2,
|
||||
conv_iso88591 } convert = conv_none;
|
||||
SECItem avaValue = { siBuffer, 0 };
|
||||
PORTCheapArenaPool tmpArena;
|
||||
|
||||
if (!derAVAValue || !derAVAValue->len || !derAVAValue->data) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (derAVAValue->data[0]) {
|
||||
case SEC_ASN1_UNIVERSAL_STRING:
|
||||
convert = conv_ucs4;
|
||||
theTemplate = SEC_ASN1_GET(SEC_UniversalStringTemplate);
|
||||
break;
|
||||
case SEC_ASN1_IA5_STRING:
|
||||
theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate);
|
||||
break;
|
||||
case SEC_ASN1_PRINTABLE_STRING:
|
||||
theTemplate = SEC_ASN1_GET(SEC_PrintableStringTemplate);
|
||||
break;
|
||||
case SEC_ASN1_T61_STRING:
|
||||
/*
|
||||
* Per common practice, we're not decoding actual T.61, but instead
|
||||
* treating T61-labeled strings as containing ISO-8859-1.
|
||||
*/
|
||||
convert = conv_iso88591;
|
||||
theTemplate = SEC_ASN1_GET(SEC_T61StringTemplate);
|
||||
break;
|
||||
case SEC_ASN1_BMP_STRING:
|
||||
convert = conv_ucs2;
|
||||
theTemplate = SEC_ASN1_GET(SEC_BMPStringTemplate);
|
||||
break;
|
||||
case SEC_ASN1_UTF8_STRING:
|
||||
/* No conversion needed ! */
|
||||
theTemplate = SEC_ASN1_GET(SEC_UTF8StringTemplate);
|
||||
break;
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_AVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PORT_Memset(&avaValue, 0, sizeof(SECItem));
|
||||
PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
|
||||
if (SEC_QuickDERDecodeItem(&tmpArena.arena, &avaValue, theTemplate,
|
||||
derAVAValue) != SECSuccess) {
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (convert != conv_none) {
|
||||
unsigned int utf8ValLen = avaValue.len * 3;
|
||||
unsigned char *utf8Val =
|
||||
(unsigned char *)PORT_ArenaZAlloc(&tmpArena.arena, utf8ValLen);
|
||||
|
||||
switch (convert) {
|
||||
case conv_ucs4:
|
||||
if (avaValue.len % 4 != 0 ||
|
||||
!PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data,
|
||||
avaValue.len, utf8Val, utf8ValLen,
|
||||
&utf8ValLen)) {
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
PORT_SetError(SEC_ERROR_INVALID_AVA);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case conv_ucs2:
|
||||
if (avaValue.len % 2 != 0 ||
|
||||
!PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data,
|
||||
avaValue.len, utf8Val, utf8ValLen,
|
||||
&utf8ValLen)) {
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
PORT_SetError(SEC_ERROR_INVALID_AVA);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case conv_iso88591:
|
||||
if (!PORT_ISO88591_UTF8Conversion(avaValue.data, avaValue.len,
|
||||
utf8Val, utf8ValLen,
|
||||
&utf8ValLen)) {
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
PORT_SetError(SEC_ERROR_INVALID_AVA);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case conv_none:
|
||||
PORT_Assert(0); /* not reached */
|
||||
break;
|
||||
}
|
||||
|
||||
avaValue.data = utf8Val;
|
||||
avaValue.len = utf8ValLen;
|
||||
}
|
||||
|
||||
retItem = SECITEM_DupItem(&avaValue);
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
return retItem;
|
||||
}
|
||||
1039
security/nss/lib/certdb/stanpcertdb.c
Normal file
1039
security/nss/lib/certdb/stanpcertdb.c
Normal file
File diff suppressed because it is too large
Load diff
128
security/nss/lib/certdb/xauthkid.c
Normal file
128
security/nss/lib/certdb/xauthkid.c
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* X.509 v3 Subject Key Usage Extension
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "seccomon.h"
|
||||
#include "secdert.h"
|
||||
#include "secoidt.h"
|
||||
#include "secasn1t.h"
|
||||
#include "secasn1.h"
|
||||
#include "secport.h"
|
||||
#include "certt.h"
|
||||
#include "genname.h"
|
||||
#include "secerr.h"
|
||||
|
||||
SEC_ASN1_MKSUB(SEC_IntegerTemplate)
|
||||
SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
|
||||
|
||||
const SEC_ASN1Template CERTAuthKeyIDTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTAuthKeyID) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
|
||||
offsetof(CERTAuthKeyID, keyID), SEC_ASN1_SUB(SEC_OctetStringTemplate) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
||||
offsetof(CERTAuthKeyID, DERAuthCertIssuer), CERT_GeneralNamesTemplate },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2,
|
||||
offsetof(CERTAuthKeyID, authCertSerialNumber),
|
||||
SEC_ASN1_SUB(SEC_IntegerTemplate) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeAuthKeyID(PLArenaPool *arena, CERTAuthKeyID *value,
|
||||
SECItem *encodedValue)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
PORT_Assert(value);
|
||||
PORT_Assert(arena);
|
||||
PORT_Assert(value->DERAuthCertIssuer == NULL);
|
||||
PORT_Assert(encodedValue);
|
||||
|
||||
do {
|
||||
|
||||
/* If both of the authCertIssuer and the serial number exist, encode
|
||||
the name first. Otherwise, it is an error if one exist and the other
|
||||
is not.
|
||||
*/
|
||||
if (value->authCertIssuer) {
|
||||
if (!value->authCertSerialNumber.data) {
|
||||
PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
|
||||
break;
|
||||
}
|
||||
|
||||
value->DERAuthCertIssuer =
|
||||
cert_EncodeGeneralNames(arena, value->authCertIssuer);
|
||||
if (!value->DERAuthCertIssuer) {
|
||||
PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
|
||||
break;
|
||||
}
|
||||
} else if (value->authCertSerialNumber.data) {
|
||||
PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
|
||||
break;
|
||||
}
|
||||
|
||||
if (SEC_ASN1EncodeItem(arena, encodedValue, value,
|
||||
CERTAuthKeyIDTemplate) == NULL)
|
||||
break;
|
||||
rv = SECSuccess;
|
||||
|
||||
} while (0);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
143
security/nss/lib/certdb/xbsconst.c
Normal file
143
security/nss/lib/certdb/xbsconst.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* X.509 v3 Basic Constraints Extension
|
||||
*/
|
||||
|
||||
#include "prtypes.h"
|
||||
#include <limits.h> /* for LONG_MAX */
|
||||
#include "seccomon.h"
|
||||
#include "secdert.h"
|
||||
#include "secoidt.h"
|
||||
#include "secasn1t.h"
|
||||
#include "secasn1.h"
|
||||
#include "certt.h"
|
||||
#include "secder.h"
|
||||
#include "prprf.h"
|
||||
#include "secerr.h"
|
||||
|
||||
typedef struct EncodedContext {
|
||||
SECItem isCA;
|
||||
SECItem pathLenConstraint;
|
||||
SECItem encodedValue;
|
||||
PLArenaPool *arena;
|
||||
} EncodedContext;
|
||||
|
||||
static const SEC_ASN1Template CERTBasicConstraintsTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(EncodedContext) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */
|
||||
offsetof(EncodedContext, isCA) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
|
||||
offsetof(EncodedContext, pathLenConstraint) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static unsigned char hexTrue = 0xff;
|
||||
static unsigned char hexFalse = 0x00;
|
||||
|
||||
#define GEN_BREAK(status) \
|
||||
rv = status; \
|
||||
break;
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeBasicConstraintValue(PLArenaPool *arena, CERTBasicConstraints *value,
|
||||
SECItem *encodedValue)
|
||||
{
|
||||
EncodedContext encodeContext;
|
||||
PLArenaPool *our_pool = NULL;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
do {
|
||||
PORT_Memset(&encodeContext, 0, sizeof(encodeContext));
|
||||
if (!value->isCA && value->pathLenConstraint >= 0) {
|
||||
PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
|
||||
GEN_BREAK(SECFailure);
|
||||
}
|
||||
|
||||
encodeContext.arena = arena;
|
||||
if (value->isCA == PR_TRUE) {
|
||||
encodeContext.isCA.data = &hexTrue;
|
||||
encodeContext.isCA.len = 1;
|
||||
}
|
||||
|
||||
/* If the pathLenConstraint is less than 0, then it should be
|
||||
* omitted from the encoding.
|
||||
*/
|
||||
if (value->isCA && value->pathLenConstraint >= 0) {
|
||||
our_pool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
|
||||
if (our_pool == NULL) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
GEN_BREAK(SECFailure);
|
||||
}
|
||||
if (SEC_ASN1EncodeUnsignedInteger(
|
||||
our_pool, &encodeContext.pathLenConstraint,
|
||||
(unsigned long)value->pathLenConstraint) == NULL) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
GEN_BREAK(SECFailure);
|
||||
}
|
||||
}
|
||||
if (SEC_ASN1EncodeItem(arena, encodedValue, &encodeContext,
|
||||
CERTBasicConstraintsTemplate) == NULL) {
|
||||
GEN_BREAK(SECFailure);
|
||||
}
|
||||
} while (0);
|
||||
if (our_pool)
|
||||
PORT_FreeArena(our_pool, PR_FALSE);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_DecodeBasicConstraintValue(CERTBasicConstraints *value,
|
||||
const SECItem *encodedValue)
|
||||
{
|
||||
EncodedContext decodeContext;
|
||||
PORTCheapArenaPool tmpArena;
|
||||
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;
|
||||
|
||||
PORT_InitCheapArena(&tmpArena, SEC_ASN1_DEFAULT_ARENA_SIZE);
|
||||
|
||||
rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &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_DestroyCheapArena(&tmpArena);
|
||||
return (rv);
|
||||
}
|
||||
269
security/nss/lib/certdb/xconst.c
Normal file
269
security/nss/lib/certdb/xconst.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* X.509 Extension Encoding
|
||||
*/
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "seccomon.h"
|
||||
#include "secdert.h"
|
||||
#include "secoidt.h"
|
||||
#include "secasn1t.h"
|
||||
#include "secasn1.h"
|
||||
#include "cert.h"
|
||||
#include "secder.h"
|
||||
#include "prprf.h"
|
||||
#include "xconst.h"
|
||||
#include "genname.h"
|
||||
#include "secasn1.h"
|
||||
#include "secerr.h"
|
||||
|
||||
static const SEC_ASN1Template CERTSubjectKeyIDTemplate[] = {
|
||||
{ SEC_ASN1_OCTET_STRING }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template CERTIA5TypeTemplate[] = {
|
||||
{ SEC_ASN1_IA5_STRING }
|
||||
};
|
||||
|
||||
SEC_ASN1_MKSUB(SEC_GeneralizedTimeTemplate)
|
||||
|
||||
static const SEC_ASN1Template CERTPrivateKeyUsagePeriodTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPrivKeyUsagePeriod) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
|
||||
offsetof(CERTPrivKeyUsagePeriod, notBefore),
|
||||
SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
|
||||
offsetof(CERTPrivKeyUsagePeriod, notAfter),
|
||||
SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERTAltNameTemplate[] = {
|
||||
{ SEC_ASN1_CONSTRUCTED, offsetof(CERTAltNameEncodedContext, encodedGenName),
|
||||
CERT_GeneralNamesTemplate }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERTAuthInfoAccessItemTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTAuthInfoAccess) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(CERTAuthInfoAccess, method) },
|
||||
{ SEC_ASN1_ANY, offsetof(CERTAuthInfoAccess, derLocation) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template CERTAuthInfoAccessTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE_OF, 0, CERTAuthInfoAccessItemTemplate }
|
||||
};
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeSubjectKeyID(PLArenaPool *arena, const SECItem *srcString,
|
||||
SECItem *encodedValue)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
if (!srcString) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (SEC_ASN1EncodeItem(arena, encodedValue, srcString,
|
||||
CERTSubjectKeyIDTemplate) == NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodePrivateKeyUsagePeriod(PLArenaPool *arena,
|
||||
CERTPrivKeyUsagePeriod *pkup,
|
||||
SECItem *encodedValue)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
if (SEC_ASN1EncodeItem(arena, encodedValue, pkup,
|
||||
CERTPrivateKeyUsagePeriodTemplate) == NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeIA5TypeExtension(PLArenaPool *arena, char *value,
|
||||
SECItem *encodedValue)
|
||||
{
|
||||
SECItem encodeContext;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
PORT_Memset(&encodeContext, 0, sizeof(encodeContext));
|
||||
|
||||
if (value != NULL) {
|
||||
encodeContext.data = (unsigned char *)value;
|
||||
encodeContext.len = strlen(value);
|
||||
}
|
||||
if (SEC_ASN1EncodeItem(arena, encodedValue, &encodeContext,
|
||||
CERTIA5TypeTemplate) == NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeAltNameExtension(PLArenaPool *arena, CERTGeneralName *value,
|
||||
SECItem *encodedValue)
|
||||
{
|
||||
SECItem **encodedGenName;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
encodedGenName = cert_EncodeGeneralNames(arena, value);
|
||||
if (SEC_ASN1EncodeItem(arena, encodedValue, &encodedGenName,
|
||||
CERT_GeneralNamesTemplate) == NULL) {
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
CERTGeneralName *
|
||||
CERT_DecodeAltNameExtension(PLArenaPool *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;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeNameConstraintsExtension(PLArenaPool *arena,
|
||||
CERTNameConstraints *value,
|
||||
SECItem *encodedValue)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
rv = cert_EncodeNameConstraints(value, arena, encodedValue);
|
||||
return rv;
|
||||
}
|
||||
|
||||
CERTNameConstraints *
|
||||
CERT_DecodeNameConstraintsExtension(PLArenaPool *arena,
|
||||
const SECItem *encodedConstraints)
|
||||
{
|
||||
return cert_DecodeNameConstraints(arena, encodedConstraints);
|
||||
}
|
||||
|
||||
CERTAuthInfoAccess **
|
||||
CERT_DecodeAuthInfoAccessExtension(PLArenaPool *reqArena,
|
||||
const SECItem *encodedExtension)
|
||||
{
|
||||
CERTAuthInfoAccess **info = NULL;
|
||||
SECStatus rv;
|
||||
int i;
|
||||
SECItem *newEncodedExtension;
|
||||
|
||||
if (!reqArena) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newEncodedExtension = SECITEM_ArenaDupItem(reqArena, encodedExtension);
|
||||
if (!newEncodedExtension) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv = SEC_QuickDERDecodeItem(reqArena, &info, CERTAuthInfoAccessTemplate,
|
||||
newEncodedExtension);
|
||||
if (rv != SECSuccess || info == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; info[i] != NULL; i++) {
|
||||
info[i]->location =
|
||||
CERT_DecodeGeneralName(reqArena, &(info[i]->derLocation), NULL);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_EncodeInfoAccessExtension(PLArenaPool *arena, CERTAuthInfoAccess **info,
|
||||
SECItem *dest)
|
||||
{
|
||||
SECItem *dummy;
|
||||
int i;
|
||||
|
||||
PORT_Assert(info != NULL);
|
||||
PORT_Assert(dest != NULL);
|
||||
if (info == NULL || dest == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
for (i = 0; info[i] != NULL; i++) {
|
||||
if (CERT_EncodeGeneralName(info[i]->location, &(info[i]->derLocation),
|
||||
arena) == NULL)
|
||||
/* Note that this may leave some of the locations filled in. */
|
||||
return SECFailure;
|
||||
}
|
||||
dummy = SEC_ASN1EncodeItem(arena, dest, &info, CERTAuthInfoAccessTemplate);
|
||||
if (dummy == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
30
security/nss/lib/certdb/xconst.h
Normal file
30
security/nss/lib/certdb/xconst.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef _XCONST_H_
|
||||
#define _XCONST_H_
|
||||
|
||||
#include "certt.h"
|
||||
|
||||
typedef struct CERTAltNameEncodedContextStr {
|
||||
SECItem **encodedGenName;
|
||||
} CERTAltNameEncodedContext;
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
extern SECStatus CERT_EncodePrivateKeyUsagePeriod(PLArenaPool *arena,
|
||||
CERTPrivKeyUsagePeriod *pkup,
|
||||
SECItem *encodedValue);
|
||||
|
||||
extern SECStatus CERT_EncodeNameConstraintsExtension(PLArenaPool *arena,
|
||||
CERTNameConstraints *value,
|
||||
SECItem *encodedValue);
|
||||
|
||||
extern SECStatus CERT_EncodeIA5TypeExtension(PLArenaPool *arena, char *value,
|
||||
SECItem *encodedValue);
|
||||
|
||||
SECStatus cert_EncodeAuthInfoAccessExtension(PLArenaPool *arena,
|
||||
CERTAuthInfoAccess **info,
|
||||
SECItem *dest);
|
||||
SEC_END_PROTOS
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue