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 + -
显示快捷键?