Back to index

lightning-sunbird  0.9+nobinonly
xcrldist.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * Code for dealing with x.509 v3 CRL Distribution Point extension.
00039  */
00040 #include "genname.h"
00041 #include "certt.h"
00042 #include "secerr.h"
00043 
00044 extern void PrepareBitStringForEncoding (SECItem *bitMap, SECItem *value);
00045 
00046 static const SEC_ASN1Template FullNameTemplate[] = {
00047     {SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0,
00048        offsetof (CRLDistributionPoint,derFullName), CERT_GeneralNamesTemplate}
00049 };
00050 
00051 static const SEC_ASN1Template RelativeNameTemplate[] = {
00052     {SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1, 
00053        offsetof (CRLDistributionPoint,distPoint.relativeName), CERT_RDNTemplate}
00054 };
00055         
00056 static const SEC_ASN1Template CRLDistributionPointTemplate[] = {
00057     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CRLDistributionPoint) },
00058        { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC |
00059            SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0,
00060            offsetof(CRLDistributionPoint,derDistPoint), SEC_AnyTemplate},
00061        { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 1,
00062            offsetof(CRLDistributionPoint,bitsmap), SEC_BitStringTemplate},
00063        { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC |
00064            SEC_ASN1_CONSTRUCTED | 2,
00065            offsetof(CRLDistributionPoint, derCrlIssuer), CERT_GeneralNamesTemplate},
00066     { 0 }
00067 };
00068 
00069 const SEC_ASN1Template CERTCRLDistributionPointsTemplate[] = {
00070     {SEC_ASN1_SEQUENCE_OF, 0, CRLDistributionPointTemplate}
00071 };
00072 
00073 SECStatus
00074 CERT_EncodeCRLDistributionPoints (PRArenaPool *arena, CERTCrlDistributionPoints *value,
00075                               SECItem *derValue)
00076 {
00077     CRLDistributionPoint **pointList, *point;
00078     PRArenaPool *ourPool = NULL;
00079     SECStatus rv = SECSuccess;
00080 
00081     PORT_Assert (derValue);
00082     PORT_Assert (value && value->distPoints);
00083 
00084     do {
00085        ourPool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
00086        if (ourPool == NULL) {
00087            rv = SECFailure;
00088            break;
00089        }    
00090        
00091        pointList = value->distPoints;
00092        while (*pointList) {
00093            point = *pointList;
00094            point->derFullName = NULL;
00095            point->derDistPoint.data = NULL;
00096 
00097            if (point->distPointType == generalName) {
00098               point->derFullName = cert_EncodeGeneralNames
00099                   (ourPool, point->distPoint.fullName);
00100               
00101               if (point->derFullName) {
00102                   rv = (SEC_ASN1EncodeItem (ourPool, &point->derDistPoint,
00103                        point, FullNameTemplate) == NULL) ? SECFailure : SECSuccess;
00104               } else {
00105                   rv = SECFailure;
00106               }
00107            }
00108            else if (point->distPointType == relativeDistinguishedName) {
00109               if (SEC_ASN1EncodeItem
00110                    (ourPool, &point->derDistPoint, 
00111                     point, RelativeNameTemplate) == NULL) 
00112                   rv = SECFailure;
00113            }
00114            /* distributionPointName is omitted */
00115            else if (point->distPointType != 0) {
00116               PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID);
00117               rv = SECFailure;
00118            }
00119            if (rv != SECSuccess)
00120               break;
00121 
00122            if (point->reasons.data)
00123               PrepareBitStringForEncoding (&point->bitsmap, &point->reasons);
00124 
00125            if (point->crlIssuer) {
00126               point->derCrlIssuer = cert_EncodeGeneralNames
00127                   (ourPool, point->crlIssuer);
00128               if (!point->crlIssuer)
00129                   break;
00130            }
00131            
00132            ++pointList;
00133        }
00134        if (rv != SECSuccess)
00135            break;
00136        if (SEC_ASN1EncodeItem
00137             (arena, derValue, value, CERTCRLDistributionPointsTemplate) == NULL) {
00138            rv = SECFailure;
00139            break;
00140        }
00141     } while (0);
00142     PORT_FreeArena (ourPool, PR_FALSE);
00143     return (rv);
00144 }
00145 
00146 CERTCrlDistributionPoints *
00147 CERT_DecodeCRLDistributionPoints (PRArenaPool *arena, SECItem *encodedValue)
00148 {
00149    CERTCrlDistributionPoints *value = NULL;    
00150    CRLDistributionPoint **pointList, *point;    
00151    SECStatus rv;
00152    SECItem newEncodedValue;
00153 
00154    PORT_Assert (arena);
00155    do {
00156        value = (CERTCrlDistributionPoints*)PORT_ArenaZAlloc (arena, sizeof (*value));
00157        if (value == NULL) {
00158            rv = SECFailure;
00159            break;
00160        }
00161 
00162         /* copy the DER into the arena, since Quick DER returns data that points
00163            into the DER input, which may get freed by the caller */
00164         rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue);
00165         if ( rv != SECSuccess ) {
00166            break;
00167         }
00168 
00169        rv = SEC_QuickDERDecodeItem
00170             (arena, &value->distPoints, CERTCRLDistributionPointsTemplate,
00171              &newEncodedValue);
00172        if (rv != SECSuccess)
00173            break;
00174 
00175        pointList = value->distPoints;
00176        while (*pointList) {
00177            point = *pointList;
00178 
00179            /* get the data if the distributionPointName is not omitted */
00180            if (point->derDistPoint.data != NULL) {
00181               point->distPointType = (DistributionPointTypes)
00182                                    ((point->derDistPoint.data[0] & 0x1f) +1);
00183               if (point->distPointType == generalName) {
00184                   SECItem innerDER;
00185               
00186                   innerDER.data = NULL;
00187                   rv = SEC_QuickDERDecodeItem
00188                       (arena, point, FullNameTemplate, &(point->derDistPoint));
00189                   if (rv != SECSuccess)
00190                      break;
00191                   point->distPoint.fullName = cert_DecodeGeneralNames
00192                      (arena, point->derFullName);
00193 
00194                   if (!point->distPoint.fullName)
00195                      break;
00196               }
00197               else if ( relativeDistinguishedName) {
00198                   rv = SEC_QuickDERDecodeItem
00199                       (arena, point, RelativeNameTemplate, &(point->derDistPoint));
00200                   if (rv != SECSuccess)
00201                      break;
00202               }
00203               else {
00204                   PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID);
00205                   break;
00206               }
00207            }
00208 
00209            /* Get the reason code if it's not omitted in the encoding */
00210            if (point->bitsmap.data != NULL) {
00211               point->reasons.data = (unsigned char*) PORT_ArenaAlloc
00212                                   (arena, (point->bitsmap.len + 7) >> 3);
00213               if (!point->reasons.data) {
00214                   rv = SECFailure;
00215                   break;
00216               }
00217               PORT_Memcpy (point->reasons.data, point->bitsmap.data,
00218                           point->reasons.len = ((point->bitsmap.len + 7) >> 3));
00219            }
00220 
00221            /* Get the crl issuer name if it's not omitted in the encoding */
00222            if (point->derCrlIssuer != NULL) {
00223               point->crlIssuer = cert_DecodeGeneralNames
00224                   (arena, point->derCrlIssuer);
00225 
00226               if (!point->crlIssuer)
00227                   break;
00228            }
00229            ++pointList;
00230        }
00231    } while (0);
00232    return (rv == SECSuccess ? value : NULL);
00233 }