oid.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,616 行 · 第 1/3 页

C
1,616
字号
/* * 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 set an error on the error  * stack. * * The error may be one of the following values: *  NSS_ERROR_INVALID_STRING *  NSS_ERROR_NO_MEMORY * * Return value: *  NULL upon error *  An NSSOID upon success */NSS_EXTERN NSSOID *nssOID_CreateFromUTF8(  NSSUTF8 *stringOid){  NSSOID *rv = (NSSOID *)NULL;  NSSOID *candidate = (NSSOID *)NULL;  PLHashEntry *e;  if( PR_SUCCESS != oid_init() ) {    return (NSSOID *)NULL;  }  if( PR_SUCCESS != oid_sanity_check_utf8(stringOid) ) {    nss_SetError(NSS_ERROR_INVALID_STRING);    return (NSSOID *)NULL;  }  candidate = oid_encode_string(stringOid);  if( (NSSOID *)NULL == candidate ) {    /* Internal error only */    return rv;  }  /*   * Does it exist?   */  PR_Lock(oid_hash_lock);  rv = (NSSOID *)PL_HashTableLookup(oid_hash_table, &candidate->data);  (void)PR_Unlock(oid_hash_lock);  if( (NSSOID *)NULL != rv ) {    /* Already exists.  Delete my copy and return the original. */    (void)nss_ZFreeIf(candidate->data.data);    (void)nss_ZFreeIf(candidate);    return rv;  }  /*    * Nope.  Add it.  Remember to allocate it out of the oid arena.   */  rv = nss_ZNEW(oid_arena, NSSOID);  if( (NSSOID *)NULL == rv ) {    goto loser;  }  rv->data.data = nss_ZAlloc(oid_arena, candidate->data.size);  if( (void *)NULL == rv->data.data ) {    goto loser;  }  rv->data.size = candidate->data.size;  nsslibc_memcpy(rv->data.data, candidate->data.data, rv->data.size);  (void)nss_ZFreeIf(candidate->data.data);  (void)nss_ZFreeIf(candidate);#ifdef DEBUG  rv->tag = "<runtime>";  rv->expl = "(OID registered at runtime)";#endif /* DEBUG */  PR_Lock(oid_hash_lock);  e = PL_HashTableAdd(oid_hash_table, &rv->data, rv);  (void)PR_Unlock(oid_hash_lock);  if( (PLHashEntry *)NULL == e ) {    nss_SetError(NSS_ERROR_NO_MEMORY);    goto loser;  }#ifdef DEBUG  {    PRStatus st;    st = oid_add_pointer(rv);    if( PR_SUCCESS != st ) {      PR_Lock(oid_hash_lock);      (void)PL_HashTableRemove(oid_hash_table, &rv->data);      (void)PR_Unlock(oid_hash_lock);      goto loser;    }  }#endif /* DEBUG */  return rv; loser:  if( (NSSOID *)NULL != candidate ) {    (void)nss_ZFreeIf(candidate->data.data);  }  (void)nss_ZFreeIf(candidate);  if( (NSSOID *)NULL != rv ) {    (void)nss_ZFreeIf(rv->data.data);  }  (void)nss_ZFreeIf(rv);  return (NSSOID *)NULL;}/* * 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 set an error on the error stack. * * The error may be one of the following values: *  NSS_ERROR_INVALID_OID *  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){  const NSSItem *it;  NSSDER *rv;  if( PR_SUCCESS != oid_init() ) {    return (NSSDER *)NULL;  }#ifdef NSSDEBUG  if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {    return (NSSDER *)NULL;  }  if( (NSSArena *)NULL != arenaOpt ) {    if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {      return (NSSDER *)NULL;    }  }#endif /* NSSDEBUG */  it = &oid->data;  if( (NSSDER *)NULL == rvOpt ) {    rv = nss_ZNEW(arenaOpt, NSSDER);    if( (NSSDER *)NULL == rv ) {      return (NSSDER *)NULL;    }  } else {    rv = rvOpt;  }  rv->data = nss_ZAlloc(arenaOpt, it->size);  if( (void *)NULL == rv->data ) {    if( rv != rvOpt ) {      (void)nss_ZFreeIf(rv);    }    return (NSSDER *)NULL;  }  rv->size = it->size;  nsslibc_memcpy(rv->data, it->data, it->size);  return rv;}/* * 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 set an error * on the error stack. * * The error may be one of the following values: *  NSS_ERROR_INVALID_OID *  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){  NSSUTF8 *rv;  PRUint8 *end;  PRUint8 *d;  PRUint8 *e;  char *a;  char *b;  PRUint32 len;  if( PR_SUCCESS != oid_init() ) {    return (NSSUTF8 *)NULL;  }#ifdef NSSDEBUG  if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {    return (NSSUTF8 *)NULL;  }  if( (NSSArena *)NULL != arenaOpt ) {    if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {      return (NSSUTF8 *)NULL;    }  }#endif /* NSSDEBUG */  a = (char *)NULL;  /* d will point to the next sequence of bytes to decode */  d = (PRUint8 *)oid->data.data;  /* end points to one past the legitimate data */  end = &d[ oid->data.size ];#ifdef NSSDEBUG  /*   * Guarantee that the for(e=d;e<end;e++) loop below will   * terminate.  Our BER sanity-checking code above will prevent   * such a BER from being registered, so the only other way one   * might show up is if our dotted-decimal encoder above screws   * up or our generated list is wrong.  So I'll wrap it with   * #ifdef NSSDEBUG and #endif.   */  if( end[-1] & 0x80 ) {    nss_SetError(NSS_ERROR_INTERNAL_ERROR);    return (NSSUTF8 *)NULL;  }#endif /* NSSDEBUG */  /*   * Check for our pseudo-encoded single-digit OIDs   */  if( (*d == 0x80) && (2 == oid->data.size) ) {    /* Funky encoding.  The second byte is the number */    a = PR_smprintf("%lu", (PRUint32)d[1]);    if( (char *)NULL == a ) {      nss_SetError(NSS_ERROR_NO_MEMORY);      return (NSSUTF8 *)NULL;    }    goto done;  }  for( ; d < end; d = &e[1] ) {        for( e = d; e < end; e++ ) {      if( 0 == (*e & 0x80) ) {        break;      }    }        if( ((e-d) > 4) || (((e-d) == 4) && (*d & 0x70)) ) {      /* More than a 32-bit number */    } else {      PRUint32 n = 0;            switch( e-d ) {      case 4:        n |= ((PRUint32)(e[-4] & 0x0f)) << 28;      case 3:        n |= ((PRUint32)(e[-3] & 0x7f)) << 21;      case 2:        n |= ((PRUint32)(e[-2] & 0x7f)) << 14;      case 1:        n |= ((PRUint32)(e[-1] & 0x7f)) <<  7;      case 0:        n |= ((PRUint32)(e[-0] & 0x7f))      ;      }            if( (char *)NULL == a ) {        /* This is the first number.. decompose it */        PRUint32 one = (n/40), two = (n%40);                a = PR_smprintf("%lu.%lu", one, two);        if( (char *)NULL == a ) {          nss_SetError(NSS_ERROR_NO_MEMORY);          return (NSSUTF8 *)NULL;        }      } else {        b = PR_smprintf("%s.%lu", a, n);        if( (char *)NULL == b ) {          PR_smprintf_free(a);          nss_SetError(NSS_ERROR_NO_MEMORY);          return (NSSUTF8 *)NULL;        }                PR_smprintf_free(a);        a = b;      }    }  } done:  /*   * Even if arenaOpt is NULL, we have to copy the data so that   * it'll be freed with the right version of free: ours, not   * PR_smprintf_free's.   */  len = PL_strlen(a);  rv = (NSSUTF8 *)nss_ZAlloc(arenaOpt, len);  if( (NSSUTF8 *)NULL == rv ) {    PR_smprintf_free(a);    return (NSSUTF8 *)NULL;  }  nsslibc_memcpy(rv, a, len);  PR_smprintf_free(a);  return rv;}/* * nssOID_getExplanation * * This method is only present in debug builds. * * This routine will return a static pointer to a UTF8-encoded string * describing (in English) the specified OID.  The memory pointed to * by the return value is not owned by the caller, and should not be * freed or modified.  Note that explanations are only provided for * the OIDs built into the NSS library; there is no way to specify an * explanation for dynamically created OIDs.  This routine is intended * only for use in debugging tools such as "derdump."  This routine * may return null upon error, in which case it will have placed an * error on the error stack. * * The error may be one of the following values: *  NSS_ERROR_INVALID_NSSOID * * Return value: *  NULL upon error *  A static pointer to a readonly, non-caller-owned UTF8-encoded *    string explaining the specified OID. */#ifdef DEBUGNSS_EXTERN const NSSUTF8 *nssOID_getExplanation(  NSSOID *oid){  if( PR_SUCCESS != oid_init() ) {    return (const NSSUTF8 *)NULL;  }#ifdef NSSDEBUG  if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {    return (NSSUTF8 *)NULL;  }#endif /* NSSDEBUG */  return oid->expl;}extern const NSSError NSS_ERROR_INVALID_NSSOID;#endif /* DEBUG *//* * nssOID_getTaggedUTF8 * * This method is only present in debug builds. * * This routine will return a pointer to a caller-owned UTF8-encoded * string containing a tagged encoding of the specified OID.  Note * that OID (component) tags are only provided for the OIDs built  * into the NSS library; there is no way to specify tags for  * dynamically created OIDs.  This routine is intended for use in * debugging tools such as "derdump."   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 set  * an error on the 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 tagged encoding of *      this NSSOID */#ifdef DEBUGNSS_EXTERN NSSUTF8 *nssOID_getTaggedUTF8(  NSSOID *oid,  NSSArena *arenaOpt){  NSSUTF8 *rv;  char *raw;  char *c;  char *a = (char *)NULL;  char *b;  PRBool done = PR_FALSE;  PRUint32 len;  if( PR_SUCCESS != oid_init() ) {    return (NSSUTF8 *)NULL;  }#ifdef NSSDEBUG  if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {    return (NSSUTF8 *)NULL;  }  if( (NSSArena *)NULL != arenaOpt ) {    if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {      return (NSSUTF8 *)NULL;    }  }#endif /* NSSDEBUG */  a = PR_smprintf("{");  if( (char *)NULL == a ) {    nss_SetError(NSS_ERROR_NO_MEMORY);    return (NSSUTF8 *)NULL;  }  /*   * What I'm doing here is getting the text version of the OID,   * e.g. 1.2.12.92, then looking up each set of leading numbers   * as oids.. e.g. "1," then "1.2," then "1.2.12," etc.  Each of   * those will have the leaf tag, and I just build up the string.   * I never said this was the most efficient way of doing it,   * but hey it's a debug-build thing, and I'm getting really tired   * of writing this stupid low-level PKI code.   */  /* I know it's all ASCII, so I can use char */  raw = (char *)nssOID_GetUTF8Encoding(oid, (NSSArena *)NULL);  if( (char *)NULL == raw ) {    return (NSSUTF8 *)NULL;  }  for( c = raw; !done; c++ ) {    NSSOID *lead;    char *lastdot;    for( ; '.' != *c; c++ ) {      if( '\0' == *c ) {        done = PR_TRUE;        break;      }    }    *c = '\0';    lead = nssOID_CreateFromUTF8((NSSUTF8 *)raw);    if( (NSSOID *)NULL == lead ) {      PR_smprintf_free(a);      nss_ZFreeIf(raw);      nss_SetError(NSS_ERROR_NO_MEMORY);      return (NSSUTF8 *)NULL;    }    lastdot = PL_strrchr(raw, '.');    if( (char *)NULL == lastdot ) {      lastdot = raw;    }    b = PR_smprintf("%s %s(%s) ", a, lead->tag, &lastdot[1]);    if( (char *)NULL == b ) {      PR_smprintf_free(a);      nss_ZFreeIf(raw);      /* drop the OID reference on the floor */      nss_SetError(NSS_ERROR_NO_MEMORY);      return (NSSUTF8 *)NULL;    }    PR_smprintf_free(a);    a = b;    if( !done ) {      *c = '.';    }  }  nss_ZFreeIf(raw);  b = PR_smprintf("%s }", a);  if( (char *)NULL == b ) {    PR_smprintf_free(a);    nss_SetError(NSS_ERROR_NO_MEMORY);    return (NSSUTF8 *)NULL;  }  len = PL_strlen(b);    rv = (NSSUTF8 *)nss_ZAlloc(arenaOpt, len+1);  if( (NSSUTF8 *)NULL == rv ) {    PR_smprintf_free(b);    return (NSSUTF8 *)NULL;  }  nsslibc_memcpy(rv, b, len);  PR_smprintf_free(b);  return rv;}extern const NSSError NSS_ERROR_INVALID_NSSOID;extern const NSSError NSS_ERROR_NO_MEMORY;#endif /* DEBUG */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?