certxutl.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:11k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /*
  34.  * Certificate Extensions handling code
  35.  *
  36.  */
  37. #include "cert.h"
  38. #include "secitem.h"
  39. #include "secoid.h"
  40. #include "secder.h"
  41. #include "secasn1.h"
  42. #include "certxutl.h"
  43. #include "secerr.h"
  44. #ifdef OLD
  45. #include "ocspti.h" /* XXX a better extensions interface would not
  46.  * require knowledge of data structures of callers */
  47. #endif
  48. static CERTCertExtension *
  49. GetExtension (CERTCertExtension **extensions, SECItem *oid)
  50. {
  51.     CERTCertExtension **exts;
  52.     CERTCertExtension *ext = NULL;
  53.     SECComparison comp;
  54.     exts = extensions;
  55.     
  56.     if (exts) {
  57. while ( *exts ) {
  58.     ext = *exts;
  59.     comp = SECITEM_CompareItem(oid, &ext->id);
  60.     if ( comp == SECEqual ) 
  61. break;
  62.     exts++;
  63. }
  64. return (*exts ? ext : NULL);
  65.     }
  66.     return (NULL);
  67. }
  68. SECStatus
  69. cert_FindExtensionByOID (CERTCertExtension **extensions, SECItem *oid, SECItem *value)
  70. {
  71.     CERTCertExtension *ext;
  72.     SECStatus rv = SECSuccess;
  73.     
  74.     ext = GetExtension (extensions, oid);
  75.     if (ext == NULL) {
  76. PORT_SetError (SEC_ERROR_EXTENSION_NOT_FOUND);
  77. return (SECFailure);
  78.     }
  79.     if (value)
  80. rv = SECITEM_CopyItem(NULL, value, &ext->value);
  81.     return (rv);
  82. }
  83.     
  84. SECStatus
  85. CERT_GetExtenCriticality (CERTCertExtension **extensions, int tag, PRBool *isCritical)
  86. {
  87.     CERTCertExtension *ext;
  88.     SECOidData *oid;
  89.     if (!isCritical)
  90. return (SECSuccess);
  91.     
  92.     /* find the extension in the extensions list */
  93.     oid = SECOID_FindOIDByTag((SECOidTag)tag);
  94.     if ( !oid ) {
  95. return(SECFailure);
  96.     }
  97.     ext = GetExtension (extensions, &oid->oid);
  98.     if (ext == NULL) {
  99. PORT_SetError (SEC_ERROR_EXTENSION_NOT_FOUND);
  100. return (SECFailure);
  101.     }
  102.     /* If the criticality is omitted, then it is false by default.
  103.        ex->critical.data is NULL */
  104.     if (ext->critical.data == NULL)
  105. *isCritical = PR_FALSE;
  106.     else
  107. *isCritical = (ext->critical.data[0] == 0xff) ? PR_TRUE : PR_FALSE;
  108.     return (SECSuccess);    
  109. }
  110. SECStatus
  111. cert_FindExtension(CERTCertExtension **extensions, int tag, SECItem *value)
  112. {
  113.     SECOidData *oid;
  114.     
  115.     oid = SECOID_FindOIDByTag((SECOidTag)tag);
  116.     if ( !oid ) {
  117. return(SECFailure);
  118.     }
  119.     return(cert_FindExtensionByOID(extensions, &oid->oid, value));
  120. }
  121. typedef struct _extNode {
  122.     struct _extNode *next;
  123.     CERTCertExtension *ext;
  124. } extNode;
  125. typedef struct {
  126.     void (*setExts)(void *object, CERTCertExtension **exts);
  127.     void *object;
  128.     PRArenaPool *ownerArena;
  129.     PRArenaPool *arena;
  130.     extNode *head;
  131.     int count;
  132. }extRec;
  133. /*
  134.  * cert_StartExtensions
  135.  *
  136.  * NOTE: This interface changed significantly to remove knowledge
  137.  *   about callers data structures (owner objects)
  138.  */
  139. void *
  140. cert_StartExtensions(void *owner, PRArenaPool *ownerArena,
  141.    void (*setExts)(void *object, CERTCertExtension **exts))
  142. {
  143.     PRArenaPool *arena;
  144.     extRec *handle;
  145.     
  146.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  147.     if ( !arena ) {
  148. return(0);
  149.     }
  150.     handle = (extRec *)PORT_ArenaAlloc(arena, sizeof(extRec));
  151.     if ( !handle ) {
  152. PORT_FreeArena(arena, PR_FALSE);
  153. return(0);
  154.     }
  155.     handle->object = owner;
  156.     handle->ownerArena = ownerArena;
  157.     handle->setExts = setExts;
  158.     handle->arena = arena;
  159.     handle->head = 0;
  160.     handle->count = 0;
  161.     
  162.     return(handle);
  163. }
  164. static unsigned char hextrue = 0xff;
  165. /*
  166.  * Note - assumes that data pointed to by oid->data will not move
  167.  */
  168. SECStatus
  169. CERT_AddExtensionByOID (void *exthandle, SECItem *oid, SECItem *value,
  170. PRBool critical, PRBool copyData)
  171. {
  172.     CERTCertExtension *ext;
  173.     SECStatus rv;
  174.     extNode *node;
  175.     extRec *handle;
  176.     
  177.     handle = (extRec *)exthandle;
  178.     /* allocate space for extension and list node */
  179.     ext = (CERTCertExtension*)PORT_ArenaZAlloc(handle->ownerArena,
  180.                                                sizeof(CERTCertExtension));
  181.     if ( !ext ) {
  182. return(SECFailure);
  183.     }
  184.     node = (extNode*)PORT_ArenaAlloc(handle->arena, sizeof(extNode));
  185.     if ( !node ) {
  186. return(SECFailure);
  187.     }
  188.     /* add to list */
  189.     node->next = handle->head;
  190.     handle->head = node;
  191.    
  192.     /* point to ext struct */
  193.     node->ext = ext;
  194.     
  195.     /* the object ID of the extension */
  196.     ext->id = *oid;
  197.     
  198.     /* set critical field */
  199.     if ( critical ) {
  200. ext->critical.data = (unsigned char*)&hextrue;
  201. ext->critical.len = 1;
  202.     }
  203.     /* set the value */
  204.     if ( copyData ) {
  205. rv = SECITEM_CopyItem(handle->ownerArena, &ext->value, value);
  206. if ( rv ) {
  207.     return(SECFailure);
  208. }
  209.     } else {
  210. ext->value = *value;
  211.     }
  212.     
  213.     handle->count++;
  214.     
  215.     return(SECSuccess);
  216. }
  217. SECStatus
  218. CERT_AddExtension(void *exthandle, int idtag, SECItem *value,
  219.      PRBool critical, PRBool copyData)
  220. {
  221.     SECOidData *oid;
  222.     
  223.     oid = SECOID_FindOIDByTag((SECOidTag)idtag);
  224.     if ( !oid ) {
  225. return(SECFailure);
  226.     }
  227.     return(CERT_AddExtensionByOID(exthandle, &oid->oid, value, critical, copyData));
  228. }
  229. SECStatus
  230. CERT_EncodeAndAddExtension(void *exthandle, int idtag, void *value,
  231.    PRBool critical, const SEC_ASN1Template *atemplate)
  232. {
  233.     extRec *handle;
  234.     SECItem *encitem;
  235.     handle = (extRec *)exthandle;
  236.     encitem = SEC_ASN1EncodeItem(handle->ownerArena, NULL, value, atemplate);
  237.     if ( encitem == NULL ) {
  238. return(SECFailure);
  239.     }
  240.     return CERT_AddExtension(exthandle, idtag, encitem, critical, PR_FALSE);
  241. }
  242. void
  243. PrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value)
  244. {
  245.   unsigned char onebyte;
  246.   unsigned int i, len = 0;
  247.   /* to prevent warning on some platform at compile time */ 
  248.   onebyte = '';   
  249.   /* Get the position of the right-most turn-on bit */ 
  250.   for (i = 0; i < (value->len ) * 8; ++i) {
  251.       if (i % 8 == 0)
  252.   onebyte = value->data[i/8];
  253.       if (onebyte & 0x80)
  254.   len = i;            
  255.       onebyte <<= 1;
  256.       
  257.   }
  258.   bitsmap->data = value->data;
  259.   /* Add one here since we work with base 1 */ 
  260.   bitsmap->len = len + 1;
  261. }
  262. SECStatus
  263. CERT_EncodeAndAddBitStrExtension (void *exthandle, int idtag,
  264.   SECItem *value, PRBool critical)
  265. {
  266.   SECItem bitsmap;
  267.   
  268.   PrepareBitStringForEncoding (&bitsmap, value);
  269.   return (CERT_EncodeAndAddExtension
  270.   (exthandle, idtag, &bitsmap, critical, SEC_BitStringTemplate));
  271. }
  272. SECStatus
  273. CERT_FinishExtensions(void *exthandle)
  274. {
  275.     extRec *handle;
  276.     extNode *node;
  277.     CERTCertExtension **exts;
  278.     SECStatus rv = SECFailure;
  279.     
  280.     handle = (extRec *)exthandle;
  281.     /* allocate space for extensions array */
  282.     exts = PORT_ArenaNewArray(handle->ownerArena, CERTCertExtension *,
  283.       handle->count + 1);
  284.     if (exts == NULL) {
  285. goto loser;
  286.     }
  287.     /* put extensions in owner object and update its version number */
  288. #ifdef OLD
  289.     switch (handle->type) {
  290.       case CertificateExtensions:
  291. handle->owner.cert->extensions = exts;
  292. DER_SetUInteger (ownerArena, &(handle->owner.cert->version),
  293.  SEC_CERTIFICATE_VERSION_3);
  294. break;
  295.       case CrlExtensions:
  296. handle->owner.crl->extensions = exts;
  297. DER_SetUInteger (ownerArena, &(handle->owner.crl->version),
  298.  SEC_CRL_VERSION_2);
  299. break;
  300.       case OCSPRequestExtensions:
  301. handle->owner.request->tbsRequest->requestExtensions = exts;
  302. break;
  303.       case OCSPSingleRequestExtensions:
  304. handle->owner.singleRequest->singleRequestExtensions = exts;
  305. break;
  306.       case OCSPResponseSingleExtensions:
  307. handle->owner.singleResponse->singleExtensions = exts;
  308. break;
  309.     }
  310. #endif
  311.     handle->setExts(handle->object, exts);
  312.     /* update the version number */
  313.     /* copy each extension pointer */
  314.     node = handle->head;
  315.     while ( node ) {
  316. *exts = node->ext;
  317. node = node->next;
  318. exts++;
  319.     }
  320.     /* terminate the array of extensions */
  321.     *exts = 0;
  322.     rv = SECSuccess;
  323. loser:
  324.     /* free working arena */
  325.     PORT_FreeArena(handle->arena, PR_FALSE);
  326.     return rv;
  327. }
  328. /*
  329.  * get the value of the Netscape Certificate Type Extension
  330.  */
  331. SECStatus
  332. CERT_FindBitStringExtension (CERTCertExtension **extensions, int tag,
  333.      SECItem *retItem)
  334. {
  335.     SECItem wrapperItem, tmpItem = {siBuffer,0};
  336.     SECStatus rv;
  337.     PRArenaPool *arena = NULL;
  338.     
  339.     wrapperItem.data = NULL;
  340.     tmpItem.data = NULL;
  341.     
  342.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  343.     
  344.     if ( ! arena ) {
  345. return(SECFailure);
  346.     }
  347.     
  348.     rv = cert_FindExtension(extensions, tag, &wrapperItem);
  349.     if ( rv != SECSuccess ) {
  350. goto loser;
  351.     }
  352.     rv = SEC_ASN1DecodeItem(arena, &tmpItem, SEC_BitStringTemplate, 
  353.     &wrapperItem);
  354.     if ( rv != SECSuccess ) {
  355. goto loser;
  356.     }
  357.     retItem->data = (unsigned char *)PORT_Alloc( ( tmpItem.len + 7 ) >> 3 );
  358.     if ( retItem->data == NULL ) {
  359. goto loser;
  360.     }
  361.     
  362.     PORT_Memcpy(retItem->data, tmpItem.data, ( tmpItem.len + 7 ) >> 3);
  363.     retItem->len = tmpItem.len;
  364.     
  365.     rv = SECSuccess;
  366.     goto done;
  367.     
  368. loser:
  369.     rv = SECFailure;
  370. done:
  371.     if ( arena ) {
  372. PORT_FreeArena(arena, PR_FALSE);
  373.     }
  374.     
  375.     if ( wrapperItem.data ) {
  376. PORT_Free(wrapperItem.data);
  377.     }
  378.     return(rv);
  379. }
  380. PRBool
  381. cert_HasCriticalExtension (CERTCertExtension **extensions)
  382. {
  383.     CERTCertExtension **exts;
  384.     CERTCertExtension *ext = NULL;
  385.     PRBool hasCriticalExten = PR_FALSE;
  386.     
  387.     exts = extensions;
  388.     
  389.     if (exts) {
  390. while ( *exts ) {
  391.     ext = *exts;
  392.     /* If the criticality is omitted, it's non-critical */
  393.     if (ext->critical.data && ext->critical.data[0] == 0xff) {
  394. hasCriticalExten = PR_TRUE;
  395. break;
  396.     }
  397.     exts++;
  398. }
  399.     }
  400.     return (hasCriticalExten);
  401. }
  402. PRBool
  403. cert_HasUnknownCriticalExten (CERTCertExtension **extensions)
  404. {
  405.     CERTCertExtension **exts;
  406.     CERTCertExtension *ext = NULL;
  407.     PRBool hasUnknownCriticalExten = PR_FALSE;
  408.     
  409.     exts = extensions;
  410.     
  411.     if (exts) {
  412. while ( *exts ) {
  413.     ext = *exts;
  414.     /* If the criticality is omitted, it's non-critical.
  415.        If an extension is critical, make sure that we know
  416.        how to process the extension.
  417.              */
  418.     if (ext->critical.data && ext->critical.data[0] == 0xff) {
  419. if (SECOID_KnownCertExtenOID (&ext->id) == PR_FALSE) {
  420.     hasUnknownCriticalExten = PR_TRUE;
  421.     break;
  422. }
  423.     }
  424.     exts++;
  425. }
  426.     }
  427.     return (hasUnknownCriticalExten);
  428. }