oid.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,616 行 · 第 1/3 页
C
1,616 行
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#ifdef DEBUGstatic const char CVS_ID[] = "@(#) $RCSfile: oid.c,v $ $Revision: 1.1 $ $Date: 2000/03/31 19:16:22 $ $Name: NSS_3_1_1_RTM $";#endif /* DEBUG *//* * oid.c * * This file contains the implementation of the basic OID routines. */#ifndef BASE_H#include "base.h"#endif /* BASE_H */#ifndef PKI1_H#include "pki1.h"#endif /* PKI1_H */#include "plhash.h"#include "plstr.h"/* * NSSOID * * The public "methods" regarding this "object" are: * * NSSOID_CreateFromBER -- constructor * NSSOID_CreateFromUTF8 -- constructor * (there is no explicit destructor) * * NSSOID_GetDEREncoding * NSSOID_GetUTF8Encoding * The non-public "methods" regarding this "object" are: * * nssOID_CreateFromBER -- constructor * nssOID_CreateFromUTF8 -- constructor * (there is no explicit destructor) * * nssOID_GetDEREncoding * nssOID_GetUTF8Encoding * * In debug builds, the following non-public calls are also available: * * nssOID_verifyPointer * nssOID_getExplanation * nssOID_getTaggedUTF8 */const NSSOID *NSS_OID_UNKNOWN = (NSSOID *)NULL;/* * First, the public "wrappers" *//* * NSSOID_CreateFromBER * * This routine creates an NSSOID by decoding a BER- or DER-encoded * OID. It may return NULL upon error, in which case it * will have created an error stack. * * The error may be one of the following values: * NSS_ERROR_INVALID_BER * NSS_ERROR_NO_MEMORY * * Return value: * NULL upon error * An NSSOID upon success */NSS_EXTERN NSSOID *NSSOID_CreateFromBER( NSSBER *berOid){ nss_ClearErrorStack();#ifdef DEBUG /* * NSSBERs can be created by the user, * so no pointer-tracking can be checked. */ if( (NSSBER *)NULL == berOid ) { nss_SetError(NSS_ERROR_INVALID_BER); return (NSSOID *)NULL; } if( (void *)NULL == berOid->data ) { nss_SetError(NSS_ERROR_INVALID_BER); return (NSSOID *)NULL; }#endif /* DEBUG */ return nssOID_CreateFromBER(berOid);}/* * NSSOID_CreateFromUTF8 * * This routine creates an NSSOID by decoding a UTF8 string * representation of an OID in dotted-number format. The string may * optionally begin with an octothorpe. It may return NULL * upon error, in which case it will have created an error stack. * * The error may be one of the following values: * NSS_ERROR_INVALID_UTF8 * NSS_ERROR_NO_MEMORY * * Return value: * NULL upon error * An NSSOID upon success */NSS_EXTERN NSSOID *NSSOID_CreateFromUTF8( NSSUTF8 *stringOid){ nss_ClearErrorStack();#ifdef DEBUG /* * NSSUTF8s can be created by the user, * so no pointer-tracking can be checked. */ if( (NSSUTF8 *)NULL == stringOid ) { nss_SetError(NSS_ERROR_INVALID_UTF8); return (NSSOID *)NULL; }#endif /* DEBUG */ return nssOID_CreateFromUTF8(stringOid);}/* * NSSOID_GetDEREncoding * * This routine returns the DER encoding of the specified NSSOID. * If the optional arena argument is non-null, the memory used will * be obtained from that arena; otherwise, the memory will be obtained * from the heap. This routine may return return null upon error, in * which case it will have created an error stack. * * The error may be one of the following values: * NSS_ERROR_INVALID_NSSOID * NSS_ERROR_NO_MEMORY * * Return value: * NULL upon error * The DER encoding of this NSSOID */NSS_EXTERN NSSDER *NSSOID_GetDEREncoding( const NSSOID *oid, NSSDER *rvOpt, NSSArena *arenaOpt){ nss_ClearErrorStack();#ifdef DEBUG if( PR_SUCCESS != nssOID_verifyPointer(oid) ) { return (NSSDER *)NULL; } if( (NSSArena *)NULL != arenaOpt ) { if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) { return (NSSDER *)NULL; } }#endif /* DEBUG */ return nssOID_GetDEREncoding(oid, rvOpt, arenaOpt);}/* * NSSOID_GetUTF8Encoding * * This routine returns a UTF8 string containing the dotted-number * encoding of the specified NSSOID. If the optional arena argument * is non-null, the memory used will be obtained from that arena; * otherwise, the memory will be obtained from the heap. This routine * may return null upon error, in which case it will have created an * error stack. * * The error may be one of the following values: * NSS_ERROR_INVALID_NSSOID * NSS_ERROR_NO_MEMORY * * Return value: * NULL upon error * A pointer to a UTF8 string containing the dotted-digit encoding of * this NSSOID */NSS_EXTERN NSSUTF8 *NSSOID_GetUTF8Encoding( const NSSOID *oid, NSSArena *arenaOpt){ nss_ClearErrorStack();#ifdef DEBUG if( PR_SUCCESS != nssOID_verifyPointer(oid) ) { return (NSSUTF8 *)NULL; } if( (NSSArena *)NULL != arenaOpt ) { if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) { return (NSSUTF8 *)NULL; } }#endif /* DEBUG */ return nssOID_GetUTF8Encoding(oid, arenaOpt);}/* * Next, some internal bookkeeping; including the OID "tag" table * and the debug-version pointer tracker. *//* * For implementation reasons (so NSSOIDs can be compared with ==), * we hash all NSSOIDs. This is the hash table. */static PLHashTable *oid_hash_table;/* * And this is its lock. */static PRLock *oid_hash_lock;/* * This is the hash function. We simply XOR the encoded form with * itself in sizeof(PLHashNumber)-byte chunks. Improving this * routine is left as an excercise for the more mathematically * inclined student. */static PR_CALLBACK PLHashNumberoid_hash( const void *key){ const NSSItem *item = (const NSSItem *)key; PLHashNumber rv = 0; PRUint8 *data = (PRUint8 *)item->data; PRUint32 i; PRUint8 *rvc = (PRUint8 *)&rv; for( i = 0; i < item->size; i++ ) { rvc[ i % sizeof(rv) ] ^= *data; data++; } return rv;}/* * This is the key-compare function. It simply does a lexical * comparison on the encoded OID form. This does not result in * quite the same ordering as the "sequence of numbers" order, * but heck it's only used internally by the hash table anyway. */static PR_CALLBACK PRIntnoid_hash_compare( const void *k1, const void *k2){ PRIntn rv; const NSSItem *i1 = (const NSSItem *)k1; const NSSItem *i2 = (const NSSItem *)k2; PRUint32 size = (i1->size < i2->size) ? i1->size : i2->size; rv = (PRIntn)nsslibc_memcmp(i1->data, i2->data, size, (PRStatus *)NULL); if( 0 == rv ) { rv = i1->size - i2->size; } return !rv;}/* * The pointer-tracking code */#ifdef DEBUGextern const NSSError NSS_ERROR_INTERNAL_ERROR;static nssPointerTracker oid_pointer_tracker;static PRStatusoid_add_pointer( const NSSOID *oid){ PRStatus rv; rv = nssPointerTracker_initialize(&oid_pointer_tracker); if( PR_SUCCESS != rv ) { return rv; } rv = nssPointerTracker_add(&oid_pointer_tracker, oid); if( PR_SUCCESS != rv ) { NSSError e = NSS_GetError(); if( NSS_ERROR_NO_MEMORY != e ) { nss_SetError(NSS_ERROR_INTERNAL_ERROR); } return rv; } return PR_SUCCESS;}#if defined(CAN_DELETE_OIDS)/* * We actually don't define NSSOID deletion, since we keep OIDs * in a hash table for easy comparison. Were we to, this is * what the pointer-removal function would look like. */static PRStatusoid_remove_pointer( const NSSOID *oid){ PRStatus rv; rv = nssPointerTracker_remove(&oid_pointer_tracker, oid); if( PR_SUCCESS != rv ) { nss_SetError(NSS_ERROR_INTERNAL_ERROR); } return rv;}#endif /* CAN_DELETE_OIDS */#endif /* DEBUG *//* * All dynamically-added OIDs get their memory from one statically- * declared arena here, merely so that any cleanup code will have * an easier time of it. */static NSSArena *oid_arena;/* * This is the call-once function which initializes the hashtable. * It creates it, then prepopulates it with all of the builtin OIDs. * It also creates the aforementioned NSSArena. */static PR_CALLBACK PRStatusoid_once_func( void){ PRUint32 i; /* Initialize the arena */ oid_arena = nssArena_Create(); if( (NSSArena *)NULL == oid_arena ) { goto loser; } /* Create the hash table lock */ oid_hash_lock = PR_NewLock(); if( (PRLock *)NULL == oid_hash_lock ) { nss_SetError(NSS_ERROR_NO_MEMORY); goto loser; } /* Create the hash table */ oid_hash_table = PL_NewHashTable(0, oid_hash, oid_hash_compare, PL_CompareValues, (PLHashAllocOps *)0, (void *)0); if( (PLHashTable *)NULL == oid_hash_table ) { nss_SetError(NSS_ERROR_NO_MEMORY); goto loser; } /* And populate it with all the builtins */ for( i = 0; i < nss_builtin_oid_count; i++ ) { NSSOID *oid = (NSSOID *)&nss_builtin_oids[i]; PLHashEntry *e = PL_HashTableAdd(oid_hash_table, &oid->data, oid); if( (PLHashEntry *)NULL == e ) { nss_SetError(NSS_ERROR_NO_MEMORY); goto loser; }#ifdef DEBUG if( PR_SUCCESS != oid_add_pointer(oid) ) { goto loser; }#endif /* DEBUG */ } return PR_SUCCESS; loser: if( (PLHashTable *)NULL != oid_hash_table ) { PL_HashTableDestroy(oid_hash_table); oid_hash_table = (PLHashTable *)NULL; } if( (PRLock *)NULL != oid_hash_lock ) { PR_DestroyLock(oid_hash_lock); oid_hash_lock = (PRLock *)NULL; } if( (NSSArena *)NULL != oid_arena ) { (void)nssArena_Destroy(oid_arena); oid_arena = (NSSArena *)NULL; } return PR_FAILURE;}/* * This is NSPR's once-block. */static PRCallOnceType oid_call_once;/* * And this is our multiply-callable internal init routine, which * will call-once our call-once function. */static PRStatusoid_init( void){ return PR_CallOnce(&oid_call_once, oid_once_func);}#ifdef DEBUG/* * nssOID_verifyPointer * * This method is only present in debug builds. * * If the specified pointer is a valid pointer to an NSSOID object, * this routine will return PR_SUCCESS. Otherwise, it will put an * error on the error stack and return PR_FAILURE. * * The error may be one of the following values: * NSS_ERROR_INVALID_NSSOID * NSS_ERROR_NO_MEMORY * * Return value: * PR_SUCCESS if the pointer is valid * PR_FAILURE if it isn't */NSS_EXTERN PRStatusnssOID_verifyPointer( const NSSOID *oid){ PRStatus rv; rv = oid_init(); if( PR_SUCCESS != rv ) { return PR_FAILURE; } rv = nssPointerTracker_initialize(&oid_pointer_tracker); if( PR_SUCCESS != rv ) { return PR_FAILURE; } rv = nssPointerTracker_verify(&oid_pointer_tracker, oid); if( PR_SUCCESS != rv ) { nss_SetError(NSS_ERROR_INVALID_NSSOID); return PR_FAILURE;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?