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

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. #include "cert.h"
  34. #include "secpkcs7.h"
  35. #include "base64.h"
  36. #include "secitem.h"
  37. #include "secder.h"
  38. #include "secasn1.h"
  39. #include "secoid.h"
  40. SECStatus
  41. SEC_ReadPKCS7Certs(SECItem *pkcs7Item, CERTImportCertificateFunc f, void *arg)
  42. {
  43.     SEC_PKCS7ContentInfo *contentInfo = NULL;
  44.     SECStatus rv;
  45.     SECItem **certs;
  46.     int count;
  47.     contentInfo = SEC_PKCS7DecodeItem(pkcs7Item, NULL, NULL, NULL, NULL, NULL, 
  48.       NULL, NULL);
  49.     if ( contentInfo == NULL ) {
  50. goto loser;
  51.     }
  52.     if ( SEC_PKCS7ContentType (contentInfo) != SEC_OID_PKCS7_SIGNED_DATA ) {
  53. goto loser;
  54.     }
  55.     certs = contentInfo->content.signedData->rawCerts;
  56.     if ( certs ) {
  57. count = 0;
  58. while ( *certs ) {
  59.     count++;
  60.     certs++;
  61. }
  62. rv = (* f)(arg, contentInfo->content.signedData->rawCerts, count);
  63.     }
  64.     
  65.     rv = SECSuccess;
  66.     
  67.     goto done;
  68. loser:
  69.     rv = SECFailure;
  70.     
  71. done:
  72.     if ( contentInfo ) {
  73. SEC_PKCS7DestroyContentInfo(contentInfo);
  74.     }
  75.     return(rv);
  76. }
  77. const SEC_ASN1Template SEC_CertSequenceTemplate[] = {
  78.     { SEC_ASN1_SEQUENCE_OF,
  79.   0, SECAnyTemplate }
  80. };
  81. SECStatus
  82. SEC_ReadCertSequence(SECItem *certsItem, CERTImportCertificateFunc f, void *arg)
  83. {
  84.     SECStatus rv;
  85.     SECItem **certs;
  86.     int count;
  87.     SECItem **rawCerts = NULL;
  88.     PRArenaPool *arena;
  89.     SEC_PKCS7ContentInfo *contentInfo = NULL;
  90.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  91.     if (arena == NULL) {
  92. return SECFailure;
  93.     }
  94.     contentInfo = SEC_PKCS7DecodeItem(certsItem, NULL, NULL, NULL, NULL, NULL, 
  95.       NULL, NULL);
  96.     if ( contentInfo == NULL ) {
  97. goto loser;
  98.     }
  99.     if ( SEC_PKCS7ContentType (contentInfo) != SEC_OID_NS_TYPE_CERT_SEQUENCE ) {
  100. goto loser;
  101.     }
  102.     rv = SEC_ASN1DecodeItem(arena, &rawCerts, SEC_CertSequenceTemplate,
  103.     contentInfo->content.data);
  104.     if (rv != SECSuccess) {
  105. goto loser;
  106.     }
  107.     certs = rawCerts;
  108.     if ( certs ) {
  109. count = 0;
  110. while ( *certs ) {
  111.     count++;
  112.     certs++;
  113. }
  114. rv = (* f)(arg, rawCerts, count);
  115.     }
  116.     
  117.     rv = SECSuccess;
  118.     
  119.     goto done;
  120. loser:
  121.     rv = SECFailure;
  122.     
  123. done:
  124.     if ( contentInfo ) {
  125. SEC_PKCS7DestroyContentInfo(contentInfo);
  126.     }
  127.     if ( arena ) {
  128. PORT_FreeArena(arena, PR_FALSE);
  129.     }
  130.     
  131.     return(rv);
  132. }
  133. CERTCertificate *
  134. CERT_ConvertAndDecodeCertificate(char *certstr)
  135. {
  136.     CERTCertificate *cert;
  137.     SECStatus rv;
  138.     SECItem der;
  139.     rv = ATOB_ConvertAsciiToItem(&der, certstr);
  140.     if (rv != SECSuccess)
  141. return NULL;
  142.     cert = CERT_DecodeDERCertificate(&der, PR_TRUE, NULL);
  143.     PORT_Free(der.data);
  144.     return cert;
  145. }
  146. #define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
  147. #define NS_CERT_TRAILER "-----END CERTIFICATE-----"
  148. #define CERTIFICATE_TYPE_STRING "certificate"
  149. #define CERTIFICATE_TYPE_LEN (sizeof(CERTIFICATE_TYPE_STRING)-1)
  150. CERTPackageType
  151. CERT_CertPackageType(SECItem *package, SECItem *certitem)
  152. {
  153.     unsigned char *cp;
  154.     int seqLen, seqLenLen;
  155.     SECItem oiditem;
  156.     SECOidData *oiddata;
  157.     CERTPackageType type = certPackageNone;
  158.     
  159.     cp = package->data;
  160.     /* is a DER encoded certificate of some type? */
  161.     if ( ( *cp  & 0x1f ) == SEC_ASN1_SEQUENCE ) {
  162. cp++;
  163. if ( *cp & 0x80) {
  164.     /* Multibyte length */
  165.     seqLenLen = cp[0] & 0x7f;
  166.     
  167.     switch (seqLenLen) {
  168.       case 4:
  169. seqLen = ((unsigned long)cp[1]<<24) |
  170.     ((unsigned long)cp[2]<<16) | (cp[3]<<8) | cp[4];
  171. break;
  172.       case 3:
  173. seqLen = ((unsigned long)cp[1]<<16) | (cp[2]<<8) | cp[3];
  174. break;
  175.       case 2:
  176. seqLen = (cp[1]<<8) | cp[2];
  177. break;
  178.       case 1:
  179. seqLen = cp[1];
  180. break;
  181.       default:
  182. /* indefinite length */
  183. seqLen = 0;
  184.     }
  185.     cp += ( seqLenLen + 1 );
  186. } else {
  187.     seqLenLen = 0;
  188.     seqLen = *cp;
  189.     cp++;
  190. }
  191. /* check entire length if definite length */
  192. if ( seqLen || seqLenLen ) {
  193.     if ( package->len != ( seqLen + seqLenLen + 2 ) ) {
  194. /* not a DER package */
  195. return(type);
  196.     }
  197. }
  198. /* check the type string */
  199. /* netscape wrapped DER cert */
  200. if ( ( cp[0] == SEC_ASN1_OCTET_STRING ) &&
  201.     ( cp[1] == CERTIFICATE_TYPE_LEN ) &&
  202.     ( PORT_Strcmp((char *)&cp[2], CERTIFICATE_TYPE_STRING) ) ) {
  203.     
  204.     cp += ( CERTIFICATE_TYPE_LEN + 2 );
  205.     /* it had better be a certificate by now!! */
  206.     if ( certitem ) {
  207. certitem->data = cp;
  208. certitem->len = package->len -
  209.     ( cp - (unsigned char *)package->data );
  210.     }
  211.     type = certPackageNSCertWrap;
  212.     
  213. } else if ( cp[0] == SEC_ASN1_OBJECT_ID ) {
  214.     /* XXX - assume DER encoding of OID len!! */
  215.     oiditem.len = cp[1];
  216.     oiditem.data = (unsigned char *)&cp[2];
  217.     oiddata = SECOID_FindOID(&oiditem);
  218.     if ( oiddata == NULL ) {
  219. /* failure */
  220. return(type);
  221.     }
  222.     if ( certitem ) {
  223. certitem->data = package->data;
  224. certitem->len = package->len;
  225.     }
  226.     
  227.     switch ( oiddata->offset ) {
  228.       case SEC_OID_PKCS7_SIGNED_DATA:
  229. type = certPackagePKCS7;
  230. break;
  231.       case SEC_OID_NS_TYPE_CERT_SEQUENCE:
  232. type = certPackageNSCertSeq;
  233. break;
  234.       default:
  235. break;
  236.     }
  237.     
  238. } else {
  239.     /* it had better be a certificate by now!! */
  240.     if ( certitem ) {
  241. certitem->data = package->data;
  242. certitem->len = package->len;
  243.     }
  244.     
  245.     type = certPackageCert;
  246. }
  247.     }
  248.     return(type);
  249. }
  250. /*
  251.  * read an old style ascii or binary certificate chain
  252.  */
  253. SECStatus
  254. CERT_DecodeCertPackage(char *certbuf,
  255.        int certlen,
  256.        CERTImportCertificateFunc f,
  257.        void *arg)
  258. {
  259.     unsigned char *cp;
  260.     int seqLen, seqLenLen;
  261.     int cl;
  262.     unsigned char *bincert = NULL, *certbegin = NULL, *certend = NULL;
  263.     unsigned int binLen;
  264.     char *ascCert = NULL;
  265.     int asciilen;
  266.     CERTCertificate *cert;
  267.     SECItem certitem, oiditem;
  268.     SECStatus rv;
  269.     SECOidData *oiddata;
  270.     SECItem *pcertitem = &certitem;
  271.     
  272.     if ( certbuf == NULL ) {
  273. return(SECFailure);
  274.     }
  275.     
  276.     cert = 0;
  277.     cp = (unsigned char *)certbuf;
  278.     /* is a DER encoded certificate of some type? */
  279.     if ( ( *cp  & 0x1f ) == SEC_ASN1_SEQUENCE ) {
  280. cp++;
  281. if ( *cp & 0x80) {
  282.     /* Multibyte length */
  283.     seqLenLen = cp[0] & 0x7f;
  284.     
  285.     switch (seqLenLen) {
  286.       case 4:
  287. seqLen = ((unsigned long)cp[1]<<24) |
  288.     ((unsigned long)cp[2]<<16) | (cp[3]<<8) | cp[4];
  289. break;
  290.       case 3:
  291. seqLen = ((unsigned long)cp[1]<<16) | (cp[2]<<8) | cp[3];
  292. break;
  293.       case 2:
  294. seqLen = (cp[1]<<8) | cp[2];
  295. break;
  296.       case 1:
  297. seqLen = cp[1];
  298. break;
  299.       default:
  300. /* indefinite length */
  301. seqLen = 0;
  302.     }
  303.     cp += ( seqLenLen + 1 );
  304. } else {
  305.     seqLenLen = 0;
  306.     seqLen = *cp;
  307.     cp++;
  308. }
  309. /* check entire length if definite length */
  310. if ( seqLen || seqLenLen ) {
  311.     if ( certlen != ( seqLen + seqLenLen + 2 ) ) {
  312. goto notder;
  313.     }
  314. }
  315. /* check the type string */
  316. /* netscape wrapped DER cert */
  317. if ( ( cp[0] == SEC_ASN1_OCTET_STRING ) &&
  318.     ( cp[1] == CERTIFICATE_TYPE_LEN ) &&
  319.     ( PORT_Strcmp((char *)&cp[2], CERTIFICATE_TYPE_STRING) ) ) {
  320.     
  321.     cp += ( CERTIFICATE_TYPE_LEN + 2 );
  322.     /* it had better be a certificate by now!! */
  323.     certitem.data = cp;
  324.     certitem.len = certlen - ( cp - (unsigned char *)certbuf );
  325.     
  326.     rv = (* f)(arg, &pcertitem, 1);
  327.     
  328.     return(rv);
  329. } else if ( cp[0] == SEC_ASN1_OBJECT_ID ) {
  330.     /* XXX - assume DER encoding of OID len!! */
  331.     oiditem.len = cp[1];
  332.     oiditem.data = (unsigned char *)&cp[2];
  333.     oiddata = SECOID_FindOID(&oiditem);
  334.     if ( oiddata == NULL ) {
  335. return(SECFailure);
  336.     }
  337.     certitem.data = (unsigned char*)certbuf;
  338.     certitem.len = certlen;
  339.     
  340.     switch ( oiddata->offset ) {
  341.       case SEC_OID_PKCS7_SIGNED_DATA:
  342. return(SEC_ReadPKCS7Certs(&certitem, f, arg));
  343. break;
  344.       case SEC_OID_NS_TYPE_CERT_SEQUENCE:
  345. return(SEC_ReadCertSequence(&certitem, f, arg));
  346. break;
  347.       default:
  348. break;
  349.     }
  350.     
  351. } else {
  352.     /* it had better be a certificate by now!! */
  353.     certitem.data = (unsigned char*)certbuf;
  354.     certitem.len = certlen;
  355.     
  356.     rv = (* f)(arg, &pcertitem, 1);
  357.     return(rv);
  358. }
  359.     }
  360.     /* now look for a netscape base64 ascii encoded cert */
  361. notder:
  362.     cp = (unsigned char *)certbuf;
  363.     cl = certlen;
  364.     certbegin = 0;
  365.     certend = 0;
  366.     /* find the beginning marker */
  367.     while ( cl > sizeof(NS_CERT_HEADER) ) {
  368. if ( !PORT_Strncasecmp((char *)cp, NS_CERT_HEADER,
  369.      sizeof(NS_CERT_HEADER)-1) ) {
  370.     cp = cp + sizeof(NS_CERT_HEADER);
  371.     certbegin = cp;
  372.     break;
  373. }
  374. /* skip to next eol */
  375. do {
  376.     cp++;
  377.     cl--;
  378. } while ( ( *cp != 'n') && cl );
  379. /* skip all blank lines */
  380. while ( ( *cp == 'n') && cl ) {
  381.     cp++;
  382.     cl--;
  383. }
  384.     }
  385.     if ( certbegin ) {
  386. /* find the ending marker */
  387. while ( cl > sizeof(NS_CERT_TRAILER) ) {
  388.     if ( !PORT_Strncasecmp((char *)cp, NS_CERT_TRAILER,
  389.  sizeof(NS_CERT_TRAILER)-1) ) {
  390. certend = (unsigned char *)cp;
  391. break;
  392.     }
  393.     /* skip to next eol */
  394.     do {
  395. cp++;
  396. cl--;
  397.     } while ( ( *cp != 'n') && cl );
  398.     /* skip all blank lines */
  399.     while ( ( *cp == 'n') && cl ) {
  400. cp++;
  401. cl--;
  402.     }
  403. }
  404.     }
  405.     if ( certbegin && certend ) {
  406. /* Convert the ASCII data into a nul-terminated string */
  407. asciilen = certend - certbegin;
  408. ascCert = (char *)PORT_Alloc(asciilen+1);
  409. if (!ascCert) {
  410.     rv = SECFailure;
  411.     goto loser;
  412. }
  413. PORT_Memcpy(ascCert, certbegin, asciilen);
  414. ascCert[asciilen] = '';
  415. /* convert to binary */
  416. bincert = ATOB_AsciiToData(ascCert, &binLen);
  417. if (!bincert) {
  418.     rv = SECFailure;
  419.     goto loser;
  420. }
  421. /* now recurse to decode the binary */
  422. rv = CERT_DecodeCertPackage((char *)bincert, binLen, f, arg);
  423.     } else {
  424. rv = SECFailure;
  425.     }
  426. loser:
  427.     if ( bincert ) {
  428. PORT_Free(bincert);
  429.     }
  430.     if ( ascCert ) {
  431. PORT_Free(ascCert);
  432.     }
  433.     return(rv);
  434. }
  435. typedef struct {
  436.     PRArenaPool *arena;
  437.     SECItem cert;
  438. } collect_args;
  439. static SECStatus
  440. collect_certs(void *arg, SECItem **certs, int numcerts)
  441. {
  442.     SECStatus rv;
  443.     collect_args *collectArgs;
  444.     
  445.     collectArgs = (collect_args *)arg;
  446.     
  447.     rv = SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs);
  448.     return(rv);
  449. }
  450. /*
  451.  * read an old style ascii or binary certificate
  452.  */
  453. CERTCertificate *
  454. CERT_DecodeCertFromPackage(char *certbuf, int certlen)
  455. {
  456.     collect_args collectArgs;
  457.     SECStatus rv;
  458.     CERTCertificate *cert = NULL;
  459.     
  460.     collectArgs.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  461.     
  462.     rv = CERT_DecodeCertPackage(certbuf, certlen, collect_certs,
  463. (void *)&collectArgs);
  464.     if ( rv == SECSuccess ) {
  465. cert = CERT_DecodeDERCertificate(&collectArgs.cert, PR_TRUE, NULL);
  466.     }
  467.     
  468.     PORT_FreeArena(collectArgs.arena, PR_FALSE);
  469.     
  470.     return(cert);
  471. }