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